.NetCore如何使用ImageSharp進行圖片的生成

? ? ImageSharp是對NetCore平臺擴展的一個圖像處理方案,以往網上的案例多以生成文字及畫出簡單圖形、驗證碼等方式進行探討和實踐。

? ? 今天我分享一下所在公司項目的實際應用案例,導出微信二維碼圖片,圓形頭像等等。

一、源碼獲取

? ? Git項目地址:https://github.com/SixLabors/ImageSharp

? ? 安裝這兩個包即可:

? ??Install-Package SixLabors.ImageSharp -Version?1.0.0-beta0001?

? ??Install-Package SixLabors.ImageSharp.Drawing -Version?1.0.0-beta0001?

二、應用

? ? 1.在圖片中畫出文字

? ???首先要注意字體問題,Windows自帶的字體一般存儲于 C:\Windows\Fonts?文件夾內,如果是部署在Linux系統的應用程序,則存儲于?usr/share/fonts 文件夾內。以黑體為例,我們找到對應的字體文件 SIMHEI.TTF?,將其放入項目的根目錄內方便調用。

?

 1   var path = "Image/Mud.png"                                  //圖片路徑
 2   FontCollection fonts = new FontCollection();
 3   FontFamily fontfamily = fonts.Install("Source/SIMHEI.TTF"); //字體的路徑
var font = new Font(fontfamily,50); 4 using (Image<Rgba32> image = Image.Load(path)) 5 { 6 image.Mutate(x => x.
DrawText (
8 "陸家嘴旗艦店", //文字內容 9 font, 10 Rgba32.Black, //文字顏色 11 new PointF(100,100)) //坐標位置(浮點) 12 ); 13 image.Save(path); 14 }

?

? ? ? ?關于Image.Load()獲取圖片方法的使用,可以直接讀取Stream類型的流,也可以根據圖片的本地路徑獲取。

//線上地址的圖片,通過獲取流的方式讀取   
WebRequest imgRequest = WebRequest.Create(url);
var res = (HttpWebResponse)imgRequest.GetResponse();
var image  = Image.Load(res.GetResponseStream());

? ? ? 獲取文字的像素寬度,可以使用:

  var str = "我是什么長度"  var size = TextMeasurer.Measure(str, new RendererOptions(new Font(fontfamily,50)));
var width = size.Width;

?

?

? ? ? 2.在圖片中畫出圓形的頭像

? ? ? 我在ImageSharp的源碼中,發現有畫圓形的工具類可以使用,在這里直接copy出來。

 1 using SixLabors.ImageSharp;
 2 using SixLabors.ImageSharp.PixelFormats;
 3 using SixLabors.ImageSharp.Processing;
 4 using SixLabors.Primitives;
 5 using SixLabors.Shapes;
 6 using System;
 7 using System.Collections.Generic;
 8 using System.Text;
 9 
10 namespace CodePicDownload
11 {
12     public static class CupCircularHelper
13     {
14 
15         public static IImageProcessingContext<Rgba32> ConvertToAvatar(this IImageProcessingContext<Rgba32> processingContext, Size size, float cornerRadius)
16         {
17             return processingContext.Resize(new ResizeOptions
18             {
19                 Size = size,
20                 Mode = ResizeMode.Crop
21             }).Apply(i => ApplyRoundedCorners(i, cornerRadius));
22         }
23 
24 
25         // This method can be seen as an inline implementation of an `IImageProcessor`:
26         // (The combination of `IImageOperations.Apply()` + this could be replaced with an `IImageProcessor`)
27         private static void ApplyRoundedCorners(Image<Rgba32> img, float cornerRadius)
28         {
29             IPathCollection corners = BuildCorners(img.Width, img.Height, cornerRadius);
30 
31             var graphicOptions = new GraphicsOptions(true)
32             {
33                 AlphaCompositionMode = PixelAlphaCompositionMode.DestOut // enforces that any part of this shape that has color is punched out of the background
34             };
35             // mutating in here as we already have a cloned original
36             // use any color (not Transparent), so the corners will be clipped
37             img.Mutate(x => x.Fill(graphicOptions, Rgba32.LimeGreen, corners));
38         }
39 
40         private static IPathCollection BuildCorners(int imageWidth, int imageHeight, float cornerRadius)
41         {
42             // first create a square
43             var rect = new RectangularPolygon(-0.5f, -0.5f, cornerRadius, cornerRadius);
44 
45             // then cut out of the square a circle so we are left with a corner
46             IPath cornerTopLeft = rect.Clip(new EllipsePolygon(cornerRadius - 0.5f, cornerRadius - 0.5f, cornerRadius));
47 
48             // corner is now a corner shape positions top left
49             //lets make 3 more positioned correctly, we can do that by translating the orgional artound the center of the image
50 
51             float rightPos = imageWidth - cornerTopLeft.Bounds.Width + 1;
52             float bottomPos = imageHeight - cornerTopLeft.Bounds.Height + 1;
53 
54             // move it across the width of the image - the width of the shape
55             IPath cornerTopRight = cornerTopLeft.RotateDegree(90).Translate(rightPos, 0);
56             IPath cornerBottomLeft = cornerTopLeft.RotateDegree(-90).Translate(0, bottomPos);
57             IPath cornerBottomRight = cornerTopLeft.RotateDegree(180).Translate(rightPos, bottomPos);
58 
59             return new PathCollection(cornerTopLeft, cornerBottomLeft, cornerTopRight, cornerBottomRight);
60         }
61   }
62 }

? ? ? ? ? ?有了畫圓形的方法,我們只需要調用ConvertToAvatar() 方法把方形的圖片轉為圓形,畫在圖片上即可。

1 using (Image<Rgba32> image = Image.Load("Image/Mud.png"))
2 {
3     var logoWidth = 300;
4     var logo = Image.Load("Image/Logo.png")
5 logo.Mutate(x => x.ConvertToAvatar(new Size(logoWidth, logoWidth), logoWidth / 2)); 6 image.Mutate(x => x.DrawImage(logo, new Point(100, 100), 1)); 7 Image.Save("..");
8 }

?

?

? 3.處理二維碼的BitMatrix類型

? ?我以微信獲取的二維碼類型為例,因為我的項目中二維碼是從微信公眾號平臺API獲取,在這次獲取圖片中,將BitMatrix類型轉換為流的格式從而可以通過Image.Load()方法獲取圖片信息成為了關鍵。在這里我還是引用到了System.Drawing,可以單獨提取公用方法。

?

 1         public void WriteToStream(BitMatrix QrMatrix, ImageFormat imageFormat, Stream stream)
 2         {
 3             if (imageFormat != ImageFormat.Exif && imageFormat != ImageFormat.Icon && imageFormat != ImageFormat.MemoryBmp)
 4             {
 5                 DrawingSize size = m_iSize.GetSize(QrMatrix?.Width ?? 21);
 6                 using (Bitmap bitmap = new Bitmap(size.CodeWidth, size.CodeWidth))
 7                 {
 8                     using (Graphics graphics = Graphics.FromImage(bitmap))
 9                     {
10                         Draw(graphics, QrMatrix);
11                         bitmap.Save(stream, imageFormat);
12                     }
13                 }
14             }
15         }

?

? ? ? ?這樣數據就存入了stream中,但直接用ImageSharp去Load處理過的流可能會有些問題,為了保險,我將數據流中的byte取出,實例化了一個新的MemoryStream類型。這樣,就可以獲取到二維碼的圖片了。

1 //Matrix為BitMatrix類型數據,ImageFormat我選擇了png類型
2 MemoryStream ms = new MemoryStream();   
3 WriteToStream(Matrix,System.Drawing.Imaging.ImageFormat.Png, ms);
4 byte[] data = new byte[ms.Length];
5 ms.Seek(0, SeekOrigin.Begin);
6 ms.Read(data, 0, Convert.ToInt32(ms.Length));
7 var image =  Image.Load(new MemoryStream(data));

?

? ? ? 最后附上保存后圖片的效果:

?

? ? ??本篇內容到此就結束了,非常感謝您的觀看,有機會的話,希望能夠一起討論技術,一起成長!

?

轉載于:https://www.cnblogs.com/niwan/p/11126239.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/247654.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/247654.shtml
英文地址,請注明出處:http://en.pswp.cn/news/247654.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

vue2工程

vue當然可以使用script標簽引入&#xff0c;不需任何依賴即可按照vue的語法進行使用。但中大型商用項目中&#xff0c;還是建議使用工程化方式使用vue&#xff0c;vue提供了官方腳手架vue-cli&#xff0c;可以快速構建vue項目&#xff0c;腳手架會幫助開發者創建好建議的工程目…

flutte的第一個hello world程序

用命令行創建項目&#xff1a; flutter create flutterdemo VSCode或者AS連接手機后 輸入 flutter run 編譯后就可以將默認的代碼顯示在手機上了 開始寫hello world 代碼&#xff0c;這段代碼寫在根目錄\lib\main.dart文件中&#xff0c;也是Flutter主文件。 整個代碼如下 impo…

Ajax 設置Access-Control-Allow-Origin實現跨域訪問

之前遇到的問題整理 ajax跨域訪問是一個老問題了&#xff0c;解決方法很多&#xff0c;比較常用的是JSONP方法&#xff0c;JSONP方法是一種非官方方法&#xff0c;而且這種方法只支持GET方式&#xff0c;不如POST方式安全。 即使使用jquery的jsonp方法&#xff0c;type設為POST…

vue工程webpack模板配置說明

vue工程webpack模板下的配置文件非常多&#xff0c;只能在實際開發過程中反復熟悉&#xff0c;才能漸漸體會官方將配置文件拆分細化的合理性。 主要配置文件中代碼的作用從網上摘錄了比較全的一份注釋&#xff0c;做下記錄。 dev-server.js 開發服務端配置 require(./check-v…

目錄的拼接

找到被拼接文件所在的目錄&#xff0c;然后進行拼接 import os 獲取當前目錄&#xff1a; os.path.dirname(__file__) 如下&#xff0c;被拼接文件所在目錄與當前目錄的上級目錄在同一文件夾下&#xff1a; os.path.join(os.path.dirname(os.path.dirname(__file__)),‘文件夾路…

vue-resource 攔截器(interceptor)的使用

攔截器-interceptor 在現代的一些前端框架上&#xff0c;攔截器基本上是很基礎但很重要的一環&#xff0c;比如Angular原生就支持攔截器配置&#xff0c;VUE的Axios模塊也給我們提供了攔截器配置&#xff0c;那么攔截器到底是什么&#xff0c;它有什么用&#xff1f;攔截器能幫…

【GamePlay】入門篇

【GamePlay】入門篇 游戲性編程是指通過一系列游戲系統將游戲想法變成現實的過程。 本次的簡例以NPC設計為主。 通常在進行腳本設計前&#xff0c;對NPC的屬性進行基本的添加和設定&#xff0c;諸如動畫系統、物理系統等等。 1.動畫系統 添加Animator組件&#xff0c;綁定骨骼。…

vue axios POST請求中參數以form data和request payload形式的原因

HTTP請求中&#xff0c;如果是get請求&#xff0c;那么表單參數以namevalue&name1value1的形式附到url的后面&#xff0c;如果是post請求&#xff0c;那么表單參數是在請求體中&#xff0c;也是以namevalue&name1value1的形式在請求體中。通過chrome的開發者工具可以看…

vue-resource使用

vue-resource是一個http請求插件&#xff0c;遵循promise&#xff0c;類似jquery中ajax操作。 vue-resource已不被官方推薦&#xff0c;官方推薦axios插件來操作http協議。 vue-resource中提供的方法 get(url, [options]) head(url, [options]) delete(url, [options]) jso…

HttpHttps

http協議與https Http 客戶端發送一個HTTP請求到服務器的請求消息包括以下格式&#xff1a; **請求行&#xff08;request line&#xff09;、請求頭部&#xff08;header&#xff09;、空行 和請求數據四個部分組成。** Get請求例子&#xff0c;使用Charles抓取的request&…

vue2使用axios post跳坑,封裝成模塊

終于將vue-resource替換成axios了&#xff0c;其中像application/x-www-form-urlencoded發送的頭信息以及返回的response結果這兩點都需要注意一下。 其實https://github.com/mzabriskie/axios也有說明的。因為我在vue-resource中使用了Vue.http.options.emulateJSON true;&am…

axios使用

axios和vue-resource一樣&#xff0c;是一個vue中操作http的插件&#xff0c;遵循promise&#xff0c;vue官方也推薦使用axios。 安裝axios npm i axios -S axios也是在運行時需要的&#xff0c;所以要保存在dependencies中。 引入axios import axios from axios Vue.proto…

jQuery length 和 size()區別

jQuery length和size()區別總結如下&#xff1a; 1.length是屬性&#xff0c;size()是方法。 2.如果你只是想獲取元素的個數&#xff0c;兩者效果一樣既 $("img").length 和 $("img").size() 獲取的值是一樣的&#xff1b;但是如果是獲取字符串的長…

一些關于自己的未來的東西

2019.7.4 自己大一建立對編程的基礎認識&#xff0c;確實培養了一些興趣&#xff0c;入了個門&#xff0c;不過沒有接觸到本質。大二加入到了學校的網站開發團隊&#xff0c;對網站開發后端進行了學習&#xff0c;對后臺開發也有了基礎的學習吧&#xff0c;哈哈可能以后就是要走…

Javascript面向對象編程:構造函數的繼承

今天要介紹的是&#xff0c;對象之間的"繼承"的五種方法。 比如&#xff0c;現在有一個"動物"對象的構造函數。 function Animal(){ this.species "動物"; } 還有一個"貓"對象的構造函數。 function Cat(name,color){ this.name nam…

并發與多線程

并發 并發&#xff08;concurrency&#xff09;是指CPU在某個時間段內交替處理多任務的能力。每個CPU不可能只顧著執行某個進程&#xff0c;而讓其他進程一直等待被執行。所以&#xff0c;CPU把可執行時間均分成若干份&#xff0c;每個進程執行一份或多份時間后&#xff0c;記錄…

有沒有朋友可以幫我解釋一下貼水是什么意思?

通俗易懂的講&#xff1a;貼水便宜&#xff0c;升水貴 當前&#xff0c;螺紋鋼05合約就是貼水01合約 翻譯&#xff0c;螺紋鋼05合約就是比01合約便宜 升水同理 轉載于:https://www.cnblogs.com/luoluo-123/p/11142229.html

es6常用點記錄

letconst解構賦值字符串數組函數對象SymbolSetWeakSetMapWeakMapProxyreflectProxy與Reflex結合實例classpromiseiteratorGerneratorDecorators模塊學習資料 let /* let 聲明變量 *//* es6相對于es5的全局和局部作用域&#xff0c;多了一個塊作用域&#xff0c;塊作用域里聲明的…

jquery插件封裝指南

入門 編寫一個jQuery插件開始于給jQuery.fn加入??新的功能屬性&#xff0c;此處添加的對象屬性的名稱就是你插件的名稱&#xff1a; jQuery.fn.myPlugin function(){//你自己的插件代碼};用戶非常喜歡的$符號哪里去了&#xff1f; 它仍然存在&#xff0c;但是&#xff0c;為…

synchronize原理

synchronized的三種應用方式 一. 修飾實例方法&#xff0c;作用于當前實例加鎖&#xff0c;進入同步代碼前要獲得當前實例的鎖。 二. 修飾靜態方法&#xff0c;作用于當前類對象加鎖&#xff0c;進入同步代碼前要獲得當前類對象的鎖。 三. 修飾代碼塊&#xff0c;指定加鎖對象&…