123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323 |
- 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
- {
- /// <summary>
- /// 将内容添加到底图上,返回流
- /// </summary>
- /// <param name="dto"></param>
- /// <returns>Stream图片流, Png格式</returns>
- 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);
- }
- }
- /// <summary>
- /// 图片更改圆角
- /// </summary>
- /// <param name="image"></param>
- /// <returns></returns>
- 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;
- }
- /// <summary>
- /// 缩放图片
- /// </summary>
- /// <param name="originalImage"></param>
- /// <param name="newWidth"></param>
- /// <param name="newHeight"></param>
- /// <returns></returns>
- 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
- {
- /// <summary>
- /// 文件名
- /// </summary>
- public string FileName { get; set; }
- /// <summary>
- /// 原始图片路径
- /// </summary>
- public string OriginImagePath { get; set; }
- /// <summary>
- /// 临时图片路径(需要对原始图片复制一个进行操作)
- /// </summary>
- public string TempImagePath { get; set; }
- /// <summary>
- /// 叠加内容详情
- /// </summary>
- public List<ImageSuperposeDetails> SuperposeDetails { get; set; }
- public void Clear()
- {
- foreach (var item in SuperposeDetails)
- {
- if (item.Type == SuperposeType.ImageStream)
- {
- item.ImageStream.ImageStream.Close();
- }
- }
- }
- }
- /// <summary>
- /// 图片叠加操作类型
- /// </summary>
- public enum SuperposeType
- {
- Text = 0,
- Image = 1,
- ImageStream = 2,
- ComplexText = 3
- }
- public class ImageSuperposeDetails
- {
- /// <summary>
- /// 叠加内容类型
- /// </summary>
- public SuperposeType Type { get; set; }
- /// <summary>
- /// 叠加的文字详情
- /// SuperposeType.Text时,Text不能为空
- /// </summary>
- public ImageSuperposeTextDetails Text { get; set; }
- /// <summary>
- /// 叠加的图片路径
- /// SuperposeType.Image时,Image不能为空
- /// </summary>
- public ImageSuperposeImageDetails Image { get; set; }
- /// <summary>
- /// 叠加的图片流
- /// SuperposeType.ImageStream时,ImageStream不能为空
- /// </summary>
- public ImageSuperposeImageStreamDetails ImageStream { get; set; }
- /// <summary>
- /// x坐标
- /// </summary>
- public int X { get; set; }
- /// <summary>
- /// y坐标
- /// </summary>
- public int Y { get; set; }
- }
- /// <summary>
- /// 叠加的文字详情
- /// </summary>
- public class ImageSuperposeTextDetails
- {
- /// <summary>
- /// 叠加的内容
- /// </summary>
- public string Text { get; set; }
- /// <summary>
- /// 叠加内容的颜色
- /// </summary>
- public Color Color { get; set; }
- /// <summary>
- /// 文字大小
- /// </summary>
- public int FontSize { get; set; } = 16;
- /// <summary>
- /// 字体格式
- /// </summary>
- public string FamilyName { get; set; }
- }
- /// <summary>
- /// 叠加的图片详情
- /// </summary>
- public class ImageSuperposeImageDetails
- {
- /// <summary>
- /// 叠加的图片路径
- /// </summary>
- public string ImagePath { get; set; }
- /// <summary>
- /// 宽(如果设置了,那么将覆盖图片默认的宽)
- /// </summary>
- public int? Width { get; set; }
- /// <summary>
- /// 高(如果设置了,那么将覆盖图片默认的高)
- /// </summary>
- public int? Height { get; set; }
- /// <summary>
- /// 是否需要把图片变成圆型
- /// </summary>
- public bool isFillet { get; set; }
- }
- /// <summary>
- /// 叠加的图片流详情
- /// </summary>
- public class ImageSuperposeImageStreamDetails
- {
- /// <summary>
- /// 叠加的图片路径
- /// </summary>
- public Stream ImageStream { get; set; }
- /// <summary>
- /// 宽(如果设置了,那么将覆盖图片默认的宽)
- /// </summary>
- public int? Width { get; set; }
- /// <summary>
- /// 高(如果设置了,那么将覆盖图片默认的高)
- /// </summary>
- public int? Height { get; set; }
- /// <summary>
- /// 是否需要把图片变成圆型
- /// </summary>
- public bool isFillet { get; set; }
- }
- }
|