13、在 uwp應用中,給圖片添加高斯模糊濾鏡效果(一)

来源:http://www.cnblogs.com/hebeiDGL/archive/2016/04/24/5427746.html
-Advertisement-
Play Games

如果在應用中,如果想要給app 添加模糊濾鏡,可能第一想到的是第三方類庫,比如 Win2d、lumia Imaging SDK 、WriteableBitmapEx,不可否認,這些類庫功能強大,效果也挺多的。不足就是增加了生成包尺寸,由於增加了相應 dll 的引用,在 app運行時也會增加記憶體占用。 ...


 

  如果在應用中,如果想要給app 添加模糊濾鏡,可能第一想到的是第三方類庫,比如 Win2dlumia Imaging SDK 、WriteableBitmapEx,不可否認,這些類庫功能強大,效果也挺多的。不足就是增加了生成包尺寸,由於增加了相應 dll  的引用,在 app運行時也會增加記憶體占用。如果只使用一種濾鏡效果,建議直接添加幾十行代碼自己實現,這樣開發、維護成本都會很少。並且由於 .net native 使得 uwp 的運算速度與 C++演算法的運行速度沒有差別了。

 

  這裡只討論高斯模糊濾鏡,感覺這個濾鏡在應用中適當的運用,會讓頁面形象生動,比如圖片背景使用這個濾鏡,會有一些磨砂玻璃的效果。針對高斯模糊的演算法網上也有很多,這裡使用戴震軍

大哥的曾經移植過的 windows phone7 的演算法。這裡主要解決的就是 silverlight(wpf)中 WriteableBitmap 中圖片數據 int[] 數組到 windows runtime(uwp)中 WriteableBitmap中 byte[] 的轉換。

 

  Demo 的運行效果:

1)當不運用濾鏡時 level 為 0(範圍 0-40):

 

2)當 level 為 2時:

 

3)當 level 為 10時:

 

4)當 level 為 40時:

 

 

1、顏色值的分析:

在 silverlight 或者 uwp 中,指定一個字體的前景色為綠色半透明:

<TextBlock Text="節約用電" FontSize="30" Foreground="#8800FF00"/>

顯示為:

 

則在前景色中顏色的設置信息:

 

 

2、分析 Silverlight 中 WriteableBitmap 對象中的 int[] 數組

對於 silverlight、wpf 平臺上圖片(jpg、png)的編輯 WriteablBitmap 對象中使用的 int[] 數組,每個 int 值同時包含了 A(alpha)、R(red)、G(green)、B(Blue)四個信息值,每個值的範圍是 0~255。

1)在 silverlight中,獲取圖片像素數據( int[] 數組 ):

// 100像素寬,100像素高
WriteableBitmap bitmap = new WriteableBitmap(100, 100);

// 獲取表示點陣圖 2D 紋理的數組。
int[] data = bitmap.Pixels;

 

 

當然,這個 int[] 數組是一維數組,線性排列的。

 

3、分析 UWP 中 WriteableBitmap 類中的 byte[] 數組

對於 Windows Runtime (uwp) 中 WriteableBitmap 類來說,存儲的圖片數據為  byte[] 數組。

例如,獲取一張圖片中的像素數據(msdn 文檔鏈接,WriteableBitmap):(WriteableBitmap 的圖像源數據是基礎像素緩衝區。WriteableBitmap.PixelBuffer不能直接寫入)

using (IRandomAccessStream fileStream = await file.OpenAsync(Windows.Storage.FileAccessMode.Read)) 
{
    BitmapDecoder decoder = await BitmapDecoder.CreateAsync(fileStream); 
    // Scale image to appropriate size 
    BitmapTransform transform = new BitmapTransform() {  
        ScaledWidth = Convert.ToUInt32(Scenario4WriteableBitmap.PixelWidth), 
        ScaledHeight = Convert.ToUInt32(Scenario4WriteableBitmap.PixelHeight)
    }; 
    PixelDataProvider pixelData = await decoder.GetPixelDataAsync( 
        BitmapPixelFormat.Bgra8, // WriteableBitmap 使用的是 BGRA 格式 
        BitmapAlphaMode.Straight, 
        transform, 
        ExifOrientationMode.IgnoreExifOrientation, // This sample ignores Exif orientation 
        ColorManagementMode.DoNotColorManage
    ); 
 
    // 包含圖片的解碼數據。在呈現之前可以被修改
    byte[] sourcePixels = pixelData.DetachPixelData(); 
 
    // 打開一個 image 的流,並且複製到 WriteableBitmap 的 pixel 緩衝區中
    using (Stream stream = writeableBitmap.PixelBuffer.AsStream()) 
    { 
        await stream.WriteAsync(sourcePixels, 0, sourcePixels.Length); 
    }                     
}

 

同樣,對於 1)中描述 100X100 的圖片的數據存儲,因為一個 int 可以包含 4個 byte位的信息,所以對於  100x100 的 int[] 數組值,也就是 10000個 int值組成。當轉換為 byte[] 數組值時,數組長度擴大四倍,變為 100x100x4 = 40000個 byte值。並且 byte 值是按照 B、G、R、A 的順序排列:

 

4、int[] 與 byte[] 的互相轉換

因為戴震軍大哥移植的濾鏡演算法為 windows phone7 的工程,所以圖片數據的計算是採用 silverlight中 int[] 數組的計算方式,所以這裡我只做了兩件事,一個是把  uwp 工程中源 WriteableBitmap 對象中 byte[] 數組的存儲方式,轉換為 silverlight 中的 int[] 數組的存儲方式,然後對圖片數據進行添加濾鏡演算法的處理,當處理完成時,再把處理結果 int[] 數組的數據再轉換為 uwp 中 WriteableBitmap 的 byte[] 數組的存儲方式:

1)uwp 中 byte[] 數組,轉換為 silverlight 的 int[] 數組:

 // 把 uwp 的 WriteableBitmap 對象的 PixelBuffer屬性(IBuffer)轉換為  byte[] 數組
 byte[] colorBytes = BufferToBytes(image.PixelBuffer);

 // 轉換為 silverlight 的 int[] 數組時,長度為 byte[] 數組的四分之一
 colorArray = new int[colorBytes.Length / 4];

 int a,r, g, b;
 int i = 0; // 通過 i 自加,來遍歷 byte[] 整個數組

 // 通過圖片的寬、高,分別設置 int[] 數組中每個像素的 ARGB 信息
 for (int y = 0; y < height; y++)
 {
     for (int x = 0; x < width; x++)
     {
         // int[] 數組的索引
         int index = y * width + x;
         b = colorBytes[i++]; // Blue
         g = colorBytes[i++]; // Green
         r = colorBytes[i++]; // Red
         a = colorBytes[i++]; // Alpha
         colorArray[index] = (a << 24) | (r << 16) | (g << 8) | b;  // 4個 byte值存儲為一個 int 值
     }
 }

 

 

2)當把上面的圖片數據,添加高斯模糊濾鏡效果之後,把 silverlight 中 int[] 數組的計算結果,轉換為 uwp 的 byte[] 數組:

// 拷貝
WriteableBitmap new_bitmap = await Utility.BitmapClone(wb);

// 添加高斯濾鏡效果
MyImage mi = new MyImage(new_bitmap);
GaussianBlurFilter filter = new GaussianBlurFilter();
filter.Sigma = level; 
filter.process(mi);

// 圖片添加完濾鏡的 int[] 數組
int[] array = mi.colorArray;

// byte[] 數組的長度是 int[] 數組的 4倍
byte[] result = new byte[array.Length * 4];

// 通過自加,來遍歷 byte[] 數組中的值
int j = 0;
for (int i = 0; i < array.Length; i++)
{
    // 同時把 int 值中 a、r、g、b 的排列方式,轉換為 byte數組中 b、g、r、a 的存儲方式 
    result[j++] = (byte)(array[i]);       // Blue
    result[j++] = (byte)(array[i] >> 8);  // Green
    result[j++] = (byte)(array[i] >> 16); // Red
    result[j++] = (byte)(array[i] >> 24); // Alpha
}

// Open a stream to copy the image contents to the WriteableBitmap's pixel buffer 
using (Stream stream = new_bitmap.PixelBuffer.AsStream())
{
    await stream.WriteAsync(result, 0, result.Length);
}

img.Source = new_bitmap;// 把最終 WriteableBitmap 對象賦值給 Image 控制項

 

 

5、代碼中會用到的自定義幫助類:

namespace BlurEffect_demo
{
    class Utility
    {
        /// <summary>
        /// WriteableBitmap 的拷貝
        /// </summary>
        /// <param name="bitmap"></param>
        /// <returns></returns>
        public static async Task<WriteableBitmap> BitmapClone(WriteableBitmap bitmap)
        {
            WriteableBitmap result = new WriteableBitmap(bitmap.PixelWidth, bitmap.PixelHeight);

            byte[] sourcePixels = Get_WriteableBitmap_bytes(bitmap);

            //byte[] resultPixels = new byte[sourcePixels.Length];

            //sourcePixels.CopyTo(resultPixels, 0);

            using (Stream resultStream = result.PixelBuffer.AsStream())
            {
                await resultStream.WriteAsync(sourcePixels, 0, sourcePixels.Length);
            }
            return result;
        }

        /// <summary>
        /// 獲取 WriteableBitmap 對象中的 byte[] 數組數據
        /// </summary>
        public static byte[] Get_WriteableBitmap_bytes(WriteableBitmap bitmap)
        {
            // 獲取對直接緩衝區的訪問,WriteableBitmap 的每個像素都寫入直接緩衝區。
            IBuffer bitmapBuffer = bitmap.PixelBuffer;

            //byte[] sourcePixels = new byte[bitmapBuffer.Length];
            //Windows.Security.Cryptography.CryptographicBuffer.CopyToByteArray(bitmapBuffer, out sourcePixels);
            //bitmapBuffer.CopyTo(sourcePixels);

            using (var dataReader = DataReader.FromBuffer(bitmapBuffer))
            {
                var bytes = new byte[bitmapBuffer.Capacity];
                dataReader.ReadBytes(bytes);
                return bytes;
            }
        }
    }
}

 

 

 

6、高斯濾鏡演算法這裡就不列出來了,具體可以參考 demo 工程

 

工程地址:link

 

 

參考閱讀:

1)戴震軍 :

blog : http://www.cnblogs.com/daizhj

github : https://github.com/daizhenjun/ImageFilterForWindowsPhone

2)WriteableBitmap.PixelBuffer property :https://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.media.imaging.writeablebitmap.pixelbuffer.aspx

3)WriteableBitmap class : https://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.media.imaging.writeablebitmap.aspx

4)WriteableBitmapEx : http://writeablebitmapex.codeplex.com/releases/view/612952

5)Getting Pixels of an Element(WriteableBitmap) // https://social.msdn.microsoft.com/Forums/en-US/39b3c702-caed-47e4-b7d3-b51d75cbca9b/getting-pixels-of-an-element-writeablebitmap?forum=winappswithcsharp

6) Windows 8 WriteableBitmap Pixel Arrays in C# and C++ : http://www.tuicool.com/articles/fQNvUz

7) 各種流轉換 : http://www.cnblogs.com/hebeiDGL/p/3428743.html

8) XAML images sample : https://code.msdn.microsoft.com/windowsapps/0f5d56ae-5e57-48e1-9cd9-993115b027b9/

9) 重新想象 Windows 8 Store Apps (29) - 圖片處理 : http://www.cnblogs.com/webabcd/archive/2013/05/27/3101069.html

 


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

-Advertisement-
Play Games
更多相關文章
  • EF6引入一個彈性連接的功能,也就是允許重新嘗試執行失敗的資料庫操作。某些複雜的場景中,可能需要啟用或停用重試執行的策略,但是EF框架暫時尚未提供直接的設置開關,將來可能會加入這種配置。幸運的是,很容易自己實現該設置功能。 最簡單的註冊執行策略的方法是通過基於代碼的配置。下麵代碼是一個典型的配置類, ...
  • Chapter 05 變數的更多內容 5.1類型轉換 1.無論什麼類型,所有的數據都是一系列的位,即一組0和1。變數的含義是通過解釋這些數據的方式來傳達的。最簡單的示例是char類型,這種類型用一個數字表示Unicode字元集中的一個字元。實際上,這個數字與ushort的存儲方式相同 他們都是存儲0 ...
  • AnkhSVN是一款在VS中管理Subversion的插件,您可以在VS中輕鬆的提交、更新、添加文件,而不用在命令行或資源管理器中提交。而且該插件屬於開源項目。AnkhSvn安裝下載完畢後,進行安裝,安裝嚮導安裝即可,如下步驟。【步驟1】安裝界面,見圖。 【步驟2】安裝成功 AnkhSvn連接Vis ...
  • ASP.NET 頁運行時,此頁將經歷一個生命周期,在生命周期中將執行一系列處理步驟。這些步驟包括初始化、實例化控制項、還原和維護狀態、運行事件處理程式代碼以及進行呈現。瞭解頁生命周期非常重要,因為這樣做您就能在生命周期的合適階段編寫代碼,以達到預期效果。此外,如果您要開發自定義控制項,就必須熟悉頁生命周 ...
  • 距離上一篇OpenAuth.net的文章已經有5個多月了,在這段時間里項目得到了很多朋友的認可,開源中國上面的Star數接近300,於是堅定了我做下去的信心。最近稍微清閑點,正式推出1.0版,併在阿裡雲上部署了一個線上演示(文章結尾處給出線上演示鏈接)。相比剛開始時的版本,現在整個架構已經穩定,系統 ...
  • 一、線上聊天室 1、新建解決方案 SignalROnlineChatDemo 2、新建MVC項目 SignalROnlineChatDemo.Web (無身份驗證) 3、安裝SignalR PM> install-package Microsoft.AspNet.SignalR 4、 創建一個稱為 ...
  • 調試網站時,異常出現:Unrecognized attribute 'targetFramework'. Note that attribute names are case-sensitive. Server Error in '/' Application. Configuration Erro ...
  • 概要 有些開發者在編寫方法時,可能較少地去思考一個問題:方法放在這個class中是否合適? 他們可能會覺得:這個方法已經實現xxx功能了,放在哪個class都一樣的,class不就是一個裝方法的容器嘛。 我贊同class是一個裝東西的容器,且不僅限於方法。 但是,容器是有區別的。本文要講的“移動方法... ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...