進入移動互聯網時代以來,Windows桌面開發已經很久不碰了。之前就是從做Windows開發入行的。 當年,還是C++ VC6, MFC的時代。那時候開發要查的是MSDN :-)。記憶體要自己管理, 排查記憶體泄漏(忘了釋放分配的記憶體)也是基本日常。光陰似箭,歲月如梭~! 幾年之前,北漂時需要寫一個wi ...
本文將告訴大家如何在 dotnet 的控制台模式下,採用 MAUI 自繪庫 Microsoft.Maui.Graphics 進行繪圖,設置 Microsoft.Maui.Graphics 底層調用 Microsoft.Maui.Graphics.Skia 庫的 Skia 進行具體的繪圖實現,此控制台可以跨平臺運行,我在本機 Win10 和 WSL 的 Ubuntu 上都運行過,輸出的結果圖片像素級相似。本文將告訴大家如何採用 Microsoft.Maui.Graphics 進行跨平臺的自繪
在開始之前,先理清一下概念。剛正式發佈的 MAUI 指的是一個跨平臺的 UI 框架,而 dotnet 指的是在 UI 框架下麵的運行時,這是早已實現跨平臺的了。本文所說的 Microsoft.Maui.Graphics 是屬於 MAUI 的一個組件,是 MAUI 的渲染層裡面的一個部分。相當於直接使用 Microsoft.Maui.Graphics 就是將 MAUI 的渲染裡面的一個模塊拆出來獨立使用。可以看到 MAUI 的設計上,渲染的一個模塊是可以拆處理獨立使用的
本文將從一個控制台開始,從比較基礎的層面告訴大家如何使用 Microsoft.Maui.Graphics 進行繪圖。我採用 Microsoft.Maui.Graphics.Skia 庫的 Skia 進行具體的繪圖實現,實現將畫出的內容存放到本地文件
新建一個控制台項目,我將項目放在 D:\lindexi\Code\SkiaSharp\SkiaSharp\BihuwelcairkiDelalurnere
文件夾裡面
按照慣例,安裝 Microsoft.Maui.Graphics.Skia
的 NuGet 包。為了可以在 Windows Subsystem for Linux (WSL)適用於 Linux 的 Windows 子系統上的 Ubuntu 上運行,繼續添加 SkiaSharp.NativeAssets.Linux.NoDependencies
庫,詳細請看 dotnet 修複在 Linux 上使用 SkiaSharp 提示找不到 liblibSkiaSharp 庫
添加完成庫的 csproj 項目文件內容如下
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Maui.Graphics.Skia" Version="6.0.403" />
<PackageReference Include="SkiaSharp.NativeAssets.Linux.NoDependencies" Version="2.88.0" />
</ItemGroup>
</Project>
在 Program.cs 加上命名空間引用
using Microsoft.Maui.Graphics;
using Microsoft.Maui.Graphics.Skia;
using SkiaSharp;
在 Microsoft.Maui.Graphics 里,一切的邏輯都是從 ICanvas 畫板開始。這是一個介面,可以採用 SkiaCanvas 來進行實現,代碼如下
var skiaCanvas = new SkiaCanvas();
而 SkiaCanvas 需要有一個具體的 Skia 繪製的畫板,也就是 Canvas 屬性。接下來開始構建 Skia 的畫板,採用的是圖片的方式,讓 Skia 繪製到圖片上
先新建圖片的信息
var skImageInfo = new SKImageInfo(1920, 1080, SKColorType.Bgra8888, SKAlphaType.Opaque, SKColorSpace.CreateSrgb());
我喜歡配置顏色採用 Bgra8888 的格式。在通用性上來說,這個 Bgra8888 是 B(Blue藍色) G(Green綠色) R(Red 紅色) 和 A(Alpha透明度) 每個分量各 8 個位的 32 位表示一個像素的格式,由於足夠簡單,被很多個平臺和框架和硬體所支持。儘管 Bgra8888 不是效率最高的方式,但好在簡單也方便理解,同時也在多個平臺可以方便共用,因此在不確定選什麼顏色的時候,預設採用這個格式也是不錯的
通過 SKImage.Create 方法創建出圖片,這個圖片不是只存放磁碟里的圖片,而是 Skia 的一個概念
using var skImage = SKImage.Create(skImageInfo);
為了在此 SKImage 上繪製,需要取出 SKBitmap 對象,放入到 SKCanvas 里,代碼如下
using (SKBitmap skBitmap = SKBitmap.FromImage(skImage))
{
using (var skCanvas = new SKCanvas(skBitmap))
{
}
}
於是就獲取到了 SKCanvas 的對象,可以放入到 SkiaCanvas 裡面
using (SKBitmap skBitmap = SKBitmap.FromImage(skImage))
{
using (var skCanvas = new SKCanvas(skBitmap))
{
var skiaCanvas = new SkiaCanvas();
skiaCanvas.Canvas = skCanvas;
}
}
如此即可拿到 ICanvas 的對象,這一層就是抽象的,無論具體的底層繪製採用的是什麼基礎,業務用 ICanvas 類型
var skiaCanvas = new SkiaCanvas();
skiaCanvas.Canvas = skCanvas;
ICanvas canvas = skiaCanvas;
以上就完成了將 Microsoft.Maui.Graphics 的具體繪製底層邏輯更換使用為 Skia 進行繪製。相似的可以替換為採用 WPF 進行繪製,詳細請看 WPF 使用 MAUI 的自繪製邏輯
接下來就是嘗試畫一條線段測試一下
canvas.StrokeSize = 2;
canvas.StrokeColor = Colors.Blue;
canvas.DrawLine(10, 10, 100, 10);
將畫出的內容保存到圖片文件,就需要回到 SkiaSharp 的邏輯
var fileName = $"xx.png";
skCanvas.Flush();
using (var skData = skBitmap.Encode(SKEncodedImageFormat.Png, 100))
{
var file = new FileInfo(fileName);
using (var fileStream = file.OpenWrite())
{
fileStream.SetLength(0);
skData.SaveTo(fileStream);
}
}
完成代碼,先在 Windows 上運行一下,可以看到輸出了圖片如下
接下來進入 WLS 也運行一下代碼
輸出的圖片和在 Windows 上輸出的圖片文件是完全二進位相同的
更多細節請看 繪製圖形對象 - .NET MAUI Microsoft Docs
更多的 MAUI 相關博客,還請參閱我的 博客導航
可以通過如下方式獲取本文的源代碼,先創建一個空文件夾,接著使用命令行 cd 命令進入此空文件夾,在命令行裡面輸入以下代碼,即可獲取到本文的代碼
git init
git remote add origin https://gitee.com/lindexi/lindexi_gd.git
git pull origin d910685120d0a4be91792685ada4bd9c967f6e4a
以上使用的是 gitee 的源,如果 gitee 不能訪問,請替換為 github 的源。請在命令行繼續輸入以下代碼
git remote remove origin
git remote add origin https://github.com/lindexi/lindexi_gd.git
git pull origin d910685120d0a4be91792685ada4bd9c967f6e4a
獲取代碼之後,進入 SkiaSharp\BihuwelcairkiDelalurnere
文件夾
我建立了一個 SkiaSharp 的群: 788018852 歡迎大家加入討論
博客園博客只做備份,博客發佈就不再更新,如果想看最新博客,請到 https://blog.lindexi.com/
本作品採用知識共用署名-非商業性使用-相同方式共用 4.0 國際許可協議進行許可。歡迎轉載、使用、重新發佈,但務必保留文章署名[林德熙](http://blog.csdn.net/lindexi_gd)(包含鏈接:http://blog.csdn.net/lindexi_gd ),不得用於商業目的,基於本文修改後的作品務必以相同的許可發佈。如有任何疑問,請與我[聯繫](mailto:[email protected])。