.NET 採用 SkiaSharp 生成二維碼和圖形驗證碼及圖片進行指定區域截取方法實現

来源:https://www.cnblogs.com/berkerdong/archive/2022/10/12/16779385.html
-Advertisement-
Play Games

在最新版的 .NET 平臺中,微軟在逐步放棄 System.Drawing.Imaging ,給出的理由如下: System.Drawing命名空間對某些操作系統和應用程式類型有一些限制。 在Windows, System.Drawing 依賴於GDI+操作系統附帶的本機庫。 某些Windows S ...


在最新版的 .NET 平臺中,微軟在逐步放棄 System.Drawing.Imaging ,給出的理由如下:

System.Drawing命名空間對某些操作系統和應用程式類型有一些限制。

  1. 在Windows, System.Drawing 依賴於GDI+操作系統附帶的本機庫。 某些Windows SKUS Windows Server Core 或 Windows Nano)不包含此本機庫作為 OS 的一部分。 如果使用此命名空間並且無法載入庫,則運行時將引發異常。
  2. 命名空間中的某些類型依賴於 GDI+ ,而 Windows 服務以及 ASP.NET Core 和 System.Drawing ASP.NET 應用不支持。 這些類型在System.Drawing.Common NuGet包中,並包括 System.Drawing.Bitmap 和 System.Drawing.Font 。 但是,命名空間中的基元類型(如 System.Drawing.Color 、、 和 System.Drawing.Size System.Drawing.Point System.Drawing.Rectangle )可以在任何應用程式中使用。
  3. 在 .NET 5 和早期版本中,System.Drawing.Common NuGet 包適用於 Windows、Linux 和 macOS。 但是,存在一些平臺差異。 在 Linux 和 macOS 上,GDI+功能由libgdiplus) 庫實現。 預設情況下,大多數 Linux 發行版中不會安裝此庫,也不支持 GDI+ 和 macOS 上Windows的所有功能。 還有一些平臺,其中 libgdiplus 完全不可用。 若要在 Linux 和 macOS 上使用 System.Drawing.Common 包中的類型,必須單獨安裝 libgdiplus。 有關詳細信息,請參閱在Linux 上安裝 .NET或在macOS 上安裝 .NET。
  4. 在 .NET 6 及更高版本中,System.Drawing.Common NuGet 包僅在 Windows操作系統上受支持。 有關詳細信息,請參閱 僅支持System.Drawing.Common Windows。

所以我將項目中原先使用 System.Drawing.Imaging 實現的方法採用 SkiaSharp 進行了重寫。
SkiaSharp是 Google 的Skia 圖形庫的 .NET 包裝器,可用於跨移動、伺服器和桌面平臺繪製 2D 圖形。SkiaSharp 可與 OpenGL 一起用於硬體加速渲染。SkiaSharp 最初由 Mono 開發,但現在由 Microsoft 維護,並根據MIT License提供。

依賴的 Nuget 組件如下:

  1. SkiaSharp
  2. SkiaSharp.NativeAssets.Linux
  3. SkiaSharp.QrCode
using SkiaSharp.QrCode;

namespace Common
{
    public class ImgHelper
    {

        /// <summary>
        /// 生成二維碼
        /// </summary>
        /// <param name="text">二維碼內容</param>
        /// <returns></returns>
        public static byte[] GetQrCode(string text)
        {
            using QRCodeGenerator generator = new();
            using var qr = generator.CreateQrCode(text, ECCLevel.L);
            SKImageInfo info = new(500, 500);

            using var surface = SKSurface.Create(info);
            using var canvas = surface.Canvas;
            canvas.Render(qr, info.Width, info.Height, SKColors.White, SKColors.Black);

            using var image = surface.Snapshot();
            using var data = image.Encode(SKEncodedImageFormat.Png, 100);
            return data.ToArray();
        }


        /// <summary>
        /// 從圖片截取部分區域
        /// </summary>
        /// <param name="fromImagePath">源圖路徑</param>
        /// <param name="offsetX">距上</param>
        /// <param name="offsetY">距左</param>
        /// <param name="width">寬度</param>
        /// <param name="height">高度</param>
        /// <returns></returns>
        public static byte[] Screenshot(string fromImagePath, int offsetX, int offsetY, int width, int height)
        {
            using var original = SKBitmap.Decode(fromImagePath);
            using SKBitmap bitmap = new(width, height);
            using SKCanvas canvas = new(bitmap);
            SKRect sourceRect = new(offsetX, offsetY, offsetX + width, offsetY + height);
            SKRect destRect = new(0, 0, width, height);

            canvas.DrawBitmap(original, sourceRect, destRect);

            using var img = SKImage.FromBitmap(bitmap);
            using SKData p = img.Encode(SKEncodedImageFormat.Png, 100);
            return p.ToArray();
        }


        /// <summary>
        /// 獲取圖像數字驗證碼
        /// </summary>
        /// <param name="text">驗證碼內容,如4為數字</param>
        /// <returns></returns>
        public static byte[] GetVerifyCode(string text)
        {

            int width = 128;
            int height = 45;

            Random random = new();

            //創建bitmap點陣圖
            using SKBitmap image = new(width, height, SKColorType.Bgra8888, SKAlphaType.Premul);
            //創建畫筆
            using SKCanvas canvas = new(image);
            //填充背景顏色為白色
            canvas.DrawColor(SKColors.White);

            //畫圖片的背景噪音線
            for (int i = 0; i < (width * height * 0.015); i++)
            {
                using SKPaint drawStyle = new();
                drawStyle.Color = new(Convert.ToUInt32(random.Next(Int32.MaxValue)));

                canvas.DrawLine(random.Next(0, width), random.Next(0, height), random.Next(0, width), random.Next(0, height), drawStyle);
            }

            //將文字寫到畫布上
            using (SKPaint drawStyle = new())
            {
                drawStyle.Color = SKColors.Red;
                drawStyle.TextSize = height;
                drawStyle.StrokeWidth = 1;

                float emHeight = height - (float)height * (float)0.14;
                float emWidth = ((float)width / text.Length) - ((float)width * (float)0.13);

                canvas.DrawText(text, emWidth, emHeight, drawStyle);
            }

            //畫圖片的前景噪音點
            for (int i = 0; i < (width * height * 0.6); i++)
            {
                image.SetPixel(random.Next(0, width), random.Next(0, height), new SKColor(Convert.ToUInt32(random.Next(Int32.MaxValue))));
            }

            using var img = SKImage.FromBitmap(image);
            using SKData p = img.Encode(SKEncodedImageFormat.Png, 100);
            return p.ToArray();
        }

    }

}

項目如果是在 windows 伺服器下運行則不需要任何安裝任何依賴項,如果是在 linux 服務下運行則需要安裝 libfontconfig1,如 ubuntu 的安裝命令

apt-get update
apt-get -y install libfontconfig1

如果是採用 docker 模式運行,則需要在 dockerfile 中添加如下配置,該命令適用於 debian 和 ubuntu 的 docker
RUN apt-get update && apt-get -y install libfontconfig1

至此 .NET 採用 SkiaSharp 生成二維碼和圖形驗證碼及圖片進行指定區域截取方法實現 就講解完了,有任何不明白的,可以在文章下麵評論或者私信我,歡迎大家積極的討論交流,有興趣的朋友可以關註我目前在維護的一個 .NET 基礎框架項目,項目地址如下
https://github.com/berkerdong/NetEngine.git
https://gitee.com/berkerdong/NetEngine.git


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

-Advertisement-
Play Games
更多相關文章
  • C語言中,數據與處理數據的操作(函數)是分開聲明的,這種程式方法被稱為程式性的;而在c++中,則是使用abstract data type(ADT)或class hierarchy的數據封裝 c++對於結構體和函數(不包含virtual和non-inline)的封裝並沒有增加佈局成本,對於C++而言 ...
  • 演算法步驟 將待排序序列第一個元素看做一個有序序列,把第二個元素到最後一個元素當成是未排序序列。 從頭到尾依次掃描未排序序列,將掃描到的每個元素插入有序序列的適當位置。(如果待插入的元素與有序序列中的某個元素相等,則將待插入元素插入到相等元素的後面。 代碼 import java.util.Array ...
  • 如題,作者一開始也遇到了這個比較棘手的問題。 話不多說,直接說解決方案。 這裡使用bytestring,如果是object[]的話則用repeated定義即可。 那麼問題又來了,用這個類型怎麼做到與java中的object完全轉換呢? 目前,作者發現bytestring對於java的object沒有 ...
  • 需求背景: 要求導出的Excel有水印,且水印不要是可點擊的圖片影響正常操作。 開發環境: JDK 1.8 SpringBoot v2.2.5.RELEASE 導入依賴: 1 <!-- poi 相關--> 2 <dependency> 3 <groupId>org.apache.poi</group ...
  • ##HashMap Map集合基於 鍵(key)/值(value)映射。每個鍵最多只能映射一個值。鍵可以是任何引用數據類型的值,不可重覆;值可以是任何引用數據類型的值,可以重覆;鍵值對存放無序。 HashMap常用方法 ##put/get 方法 1.put(K key, V value) 將鍵(ke ...
  • 今天幫同學解決scrapy的時候發現的,就是在我這裡能運行,在他那裡不能運行。對比scrapy的版本發現,他的是最新的(2.6.3),然後我的是2.5.0的。隨後我將他的版本也換成跟我同樣的,他的也能運行了。之後我去看了官方更新文檔,發現在2.5.1的更新上說明瞭,http的驗證需要在setting ...
  • 依賴註入 控制反轉(inversion of control,IOC)是設計模式中非常重要的思想,而依賴註入(dependency injection,DI)是控制反轉思想的一種重要的實現方式。依賴註入簡化了模塊的組裝過程,減小了模塊之間的耦合度,因此.NET Core中大量應用了依賴註入的開發模式 ...
  • 需求:在開發過程中經常需要部分數據等待的載入。可能因為某個表比較慢而卡到主線程,所以需要實現局部載入等待。(在Web肯定就ajax非同步就好做,winform就比較複雜點了) 效果圖 效果圖的主要效果沒展示出來,就這樣吧。懶了懶了! 用用戶控制項新建等待視窗 //Loding2的類 public par ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...