.NET 6使用ImageSharp給圖片新增水印

2022-11-30 18:00:31


.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; }
    }

如有不正確的地方,還望不吝指教。