經常看到有群友調侃“為什麼搞Java的總在學習JVM調優?那是因為Java爛!我們.NET就不需要搞這些!”真的是這樣嗎?今天我就用一個案例來分析一下。 昨天,一位學生問了我一個問題:他建了一個預設的ASP.NET Core Web API的項目,也就是那個WeatherForecast的預設項目模 ...
.NET 6 中,使用System.Drawing操作圖片,生成解決方案或打包的時候,會有警告,意思是System.Drawing僅在 'windows' 上受支持。微軟官方的解釋是:
System.Drawing.Common NuGet 包現在被歸為 Windows 特定的庫。 在為非 Windows 操作系統編譯時,平臺分析器會在編譯時發出警告。
在非 Windows 操作系統上,除非設置了運行時配置開關,否則將引發 TypeInitializationException 異常,其中 PlatformNotSupportedException 作為內部異常
在 .NET 6 之前,使用 System.Drawing.Common 包不會產生任何編譯時警告,也不會引發任何運行時異常。
從 .NET 6 開始,當為非 Windows 操作系統編譯引用代碼時,平臺分析器會發出編譯時警告。
當然,使用windows操作系統沒有任何問題,Linux的話,需要單獨的配置。
可以通過在runtimeconfig.json文件中將System.Drawing.EnableUnixSupport 運行時配置開關設置為來啟用對 .NET 6 中的非 Windows 平臺的支持:true
或者使用第三方庫
ImageSharp
SkiaSharp
Microsoft.Maui.Graphics
正如標題,我使用了ImageSharp來操作圖片,並給圖片添加水印
//ImageFile為圖片物理路徑,如下方的註釋
public async Task<ImageResult> WaterMark(string ImageFile)
{
ImageResult result = new ImageResult();
//var ImageFile = "D:\www\wwwroot\upload\5176caebc1404caa8b0b350181ae28ab.jpg";
var WaterMark = "D:\\www\\wwwroot\\watermark.png";
string FileName = Guid.NewGuid().ToString("N") + ".jpg";
string SavePath = "D:\\www\\wwwrootupload\\" + FileName;
string imgurl = "/upload/"+FileName;
//為了與System.Drawing.Common有所區別,引用使用全路徑
using (var image = await SixLabors.ImageSharp.Image.LoadAsync(ImageFile))
{
using (var clone = image.Clone(ctx => ctx.ApplyScalingImageWaterMark("center")))
{
await clone.SaveAsync(SavePath);
}
result.width = image.Width;
result.height = image.Height;
result.url = imgurl;
result.format = ".jpg";
result.state = true;
}
return result;
}
代碼比較簡單,首先使用SixLabors.ImageSharp.Image.LoadAsync打開圖片,然後使用ImageSharp的自定義擴展方法給圖片添加水印。
ApplyScalingImageWaterMark擴展方法:
public static class ImageSharpExtention
{
public static IImageProcessingContext ApplyScalingImageWaterMark(this IImageProcessingContext processingContext, string waterPosition = "center",string waterPath)
{
using (var mark_image = SixLabors.ImageSharp.Image.Load(waterPath))
{
int markWidth = mark_image.Width;
int markHeight = mark_image.Height;
var imgSize = processingContext.GetCurrentSize();
if (markWidth >= imgSize.Width || markHeight >= imgSize.Height) //對水印圖片進行縮放
{
if (imgSize.Width > imgSize.Height)//橫的長方形
{
markWidth = imgSize.Width / 2; //寬縮放一半
markHeight = (markWidth * imgSize.Height) / imgSize.Width;
}
else
{
markHeight = imgSize.Height / 2;
markWidth = (markHeight * imgSize.Width) / imgSize.Height;
}
mark_image.Mutate(mk => mk.Resize(markWidth, markHeight));
}
//水印圖片完成成立,開始根據位置添加水印
var position = waterPosition;
if (string.IsNullOrEmpty(position))
{
position = "center";
}
position = position.ToLower();
if (string.IsNullOrEmpty(position))
{
position = "center";
}
SixLabors.ImageSharp.Point point = new SixLabors.ImageSharp.Point();
//左上
if (position.Contains("lefttop"))
{
point.X = 10;
point.Y = 10;
}
//上中
if (position.Contains("topcenter"))
{
point.X = (imgSize.Width - mark_image.Width) / 2;
point.Y = 10;
}
//右上
if (position.Contains("righttop"))
{
point.X = (imgSize.Width - mark_image.Width) - 10;
point.Y = 10;
}
//右中
if (position.Contains("rightcenter"))
{
point.X = (imgSize.Width - mark_image.Width) - 10;
point.Y = (imgSize.Height - mark_image.Height) / 2;
}
//右下
if (position.Contains("rightbottom"))
{
point.X = (imgSize.Width - mark_image.Width) - 10;
point.Y = (imgSize.Height - mark_image.Height) - 10;
}
//下中
if (position.Contains("bottomcenter"))
{
point.X = (imgSize.Width - mark_image.Width) / 2;
point.Y = (imgSize.Height - mark_image.Height) - 10;
}
//左下
if (position.Contains("leftbottom"))
{
point.X = 10;
point.Y = (imgSize.Height - mark_image.Height) - 10;
}
//左中
if (position.Contains("leftcenter"))
{
point.X = 10;
point.Y = (imgSize.Height - mark_image.Height) / 2;
}
if (position.Contains("center"))
{
point.X = (imgSize.Width - mark_image.Width) / 2;
point.Y = (imgSize.Height - mark_image.Height) / 2;
}
float opacity=(float)0.8;//設置不透明度,0-1之間
//添加水印
return processingContext.DrawImage(mark_image,point,opacity);
}
}
}
ImageResult類:
public class ImageResult
{
/// <summary>
/// 文件名
/// </summary>
public string id { get; set; }
/// <summary>
/// 文件大小
/// </summary>
public string size { get; set; }
/// <summary>
/// 文件路徑
/// </summary>
public string url { get; set; }
/// <summary>
/// 文件格式
/// </summary>
public string format { get; set; }
/// <summary>
/// 上傳狀態
/// </summary>
public bool state { get; set; }
/// <summary>
/// 上傳消息
/// </summary>
public string msg { get; set; }
/// <summary>
/// 圖片寬
/// </summary>
public int width { get; set; }
/// <summary>
/// 圖片高
/// </summary>
public int height { get; set; }
}
如有不正確的地方,還望不吝指教。