using Microsoft.AspNetCore.Razor.TagHelpers; using Newtonsoft.Json; using NLog.Fluent; using System; using System.Collections.Generic; using System.Diagnostics; using System.Drawing; using System.Drawing.Drawing2D; using System.Drawing.Imaging; using System.Drawing.Text; using System.IO; using System.Numerics; using Wicture.DbRESTFul; using static System.Net.Mime.MediaTypeNames; using Image = System.Drawing.Image; namespace JiaZhiQuan.Common.Utils { public static class ImageSuperposeUtils { /// /// 将内容添加到底图上,返回流 /// /// /// Stream图片流, Png格式 public static Stream AddContextToImage(ImageSuperposeDTO dto) { try { // 复制原始图片到临时文件夹(复制一个防止同时修改同一个图片) File.Copy(dto.OriginImagePath, dto.TempImagePath, true); // 加载原始图片 using Image originalImage = Image.FromFile(dto.TempImagePath); using Graphics graphics = Graphics.FromImage(originalImage); // 循环//处理所有叠加内容 foreach (var item in dto.SuperposeDetails) { if (item.Type == SuperposeType.Text) { var text = item.Text; // 设置绘制文本的字体、大小和颜色 System.Drawing.Font font = new System.Drawing.Font(text.FamilyName, text.FontSize); Brush brush = new SolidBrush(text.Color); Point position = new Point(item.X, item.Y); // 绘制文本 graphics.DrawString(text.Text, font, brush, new Point(item.X, item.Y)); } else if (item.Type == SuperposeType.Image) { // 读取需要叠加的图片 var image = Image.FromFile(item.Image.ImagePath); if (item.Image.isFillet) { image = DrawTransparentRoundCornerImage(image); } // 设置坐标宽高 int width = item.Image.Width is null ? image.Width : item.Image.Width.Value, height = item.Image.Height is null ? image.Height : item.Image.Height.Value; var rectangle = new Rectangle(item.X, item.Y, width, height); graphics.DrawImage(image, rectangle); } else if (item.Type == SuperposeType.ImageStream) { if (item.ImageStream is null) { LoggerManager.Logger.Error("生成用户海报失败,图片流为空。参数:" + JsonConvert.SerializeObject(item)); } // 设置坐标宽高 int width = item.ImageStream.Width.Value, height = item.ImageStream.Height.Value; // 读取需要叠加的图片 var image = Image.FromStream(item.ImageStream.ImageStream); // 判断图片大小是否需要缩放 if (image.Width != width || image.Height != height) { image = ScaleImage(image, width, height); } // 是否圆角 if (item.ImageStream.isFillet) { image = DrawTransparentRoundCornerImage(image); } var rectangle = new Rectangle(item.X, item.Y, width, height); graphics.DrawImage(image, rectangle); image.Dispose(); } } // 保存修改后的图片 //originalImage.Save($@"C:\Users\gy\Pictures\海报\{dto.FileName}"); MemoryStream stream = new MemoryStream(); originalImage.Save(stream, ImageFormat.Png); stream.Seek(0, SeekOrigin.Begin); return stream; } finally { File.Delete(dto.TempImagePath); } } /// /// 图片更改圆角 /// /// /// private static Image DrawTransparentRoundCornerImage(Image image) { Bitmap bm = new Bitmap(image.Width, image.Height); using Graphics g = Graphics.FromImage(bm); g.FillRectangle(Brushes.Transparent, new Rectangle(0, 0, image.Width, image.Height)); // 将画布的区域设置为透明 g.Clear(Color.Transparent); // 设置绘制质量为高质量 g.SmoothingMode = SmoothingMode.HighQuality; // 创建一个圆形路径 GraphicsPath path = new GraphicsPath(); path.AddEllipse(0, 0, bm.Width, bm.Height); // 将剪辑区域设置为圆形路径 g.SetClip(path); // 在剪辑区域内绘制原始图像 g.DrawImage(image, 0, 0); // 清除剪辑区域,以便添加边框 g.ResetClip(); // 添加3px白色边框 using (Pen borderPen = new Pen(Color.White, 3)) { g.DrawEllipse(borderPen, 1, 1, bm.Width - 3, bm.Height - 3); } return bm; } /// /// 缩放图片 /// /// /// /// /// public static Bitmap ScaleImage(Image originalImage, int newWidth, int newHeight) { // 创建目标尺寸的位图对象 Bitmap scaledImage = new Bitmap(newWidth, newHeight); // 使用 Graphics 类进行绘制 using (Graphics graphics = Graphics.FromImage(scaledImage)) { // 设置绘制质量,可根据需要调整 graphics.CompositingQuality = CompositingQuality.HighQuality; graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; graphics.SmoothingMode = SmoothingMode.HighQuality; // 绘制缩放后的图片 graphics.DrawImage(originalImage, 0, 0, newWidth, newHeight); } return scaledImage; } } public class ImageSuperposeDTO { /// /// 文件名 /// public string FileName { get; set; } /// /// 原始图片路径 /// public string OriginImagePath { get; set; } /// /// 临时图片路径(需要对原始图片复制一个进行操作) /// public string TempImagePath { get; set; } /// /// 叠加内容详情 /// public List SuperposeDetails { get; set; } public void Clear() { foreach (var item in SuperposeDetails) { if (item.Type == SuperposeType.ImageStream) { item.ImageStream.ImageStream.Close(); } } } } /// /// 图片叠加操作类型 /// public enum SuperposeType { Text = 0, Image = 1, ImageStream = 2, ComplexText = 3 } public class ImageSuperposeDetails { /// /// 叠加内容类型 /// public SuperposeType Type { get; set; } /// /// 叠加的文字详情 /// SuperposeType.Text时,Text不能为空 /// public ImageSuperposeTextDetails Text { get; set; } /// /// 叠加的图片路径 /// SuperposeType.Image时,Image不能为空 /// public ImageSuperposeImageDetails Image { get; set; } /// /// 叠加的图片流 /// SuperposeType.ImageStream时,ImageStream不能为空 /// public ImageSuperposeImageStreamDetails ImageStream { get; set; } /// /// x坐标 /// public int X { get; set; } /// /// y坐标 /// public int Y { get; set; } } /// /// 叠加的文字详情 /// public class ImageSuperposeTextDetails { /// /// 叠加的内容 /// public string Text { get; set; } /// /// 叠加内容的颜色 /// public Color Color { get; set; } /// /// 文字大小 /// public int FontSize { get; set; } = 16; /// /// 字体格式 /// public string FamilyName { get; set; } } /// /// 叠加的图片详情 /// public class ImageSuperposeImageDetails { /// /// 叠加的图片路径 /// public string ImagePath { get; set; } /// /// 宽(如果设置了,那么将覆盖图片默认的宽) /// public int? Width { get; set; } /// /// 高(如果设置了,那么将覆盖图片默认的高) /// public int? Height { get; set; } /// /// 是否需要把图片变成圆型 /// public bool isFillet { get; set; } } /// /// 叠加的图片流详情 /// public class ImageSuperposeImageStreamDetails { /// /// 叠加的图片路径 /// public Stream ImageStream { get; set; } /// /// 宽(如果设置了,那么将覆盖图片默认的宽) /// public int? Width { get; set; } /// /// 高(如果设置了,那么将覆盖图片默认的高) /// public int? Height { get; set; } /// /// 是否需要把图片变成圆型 /// public bool isFillet { get; set; } } }