主要用到SixLabors.Fonts(2.1.0)和SixLabors.ImageSharp.Drawing(2.1.0)组件
这里我把组件创建成一个单独的类库,供其他模块来同意调用
ISixLaborsExtensions.cs
using SixLabors.Fonts;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Drawing.Processing;
using SixLabors.ImageSharp.Processing;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;namespace Tzkj.SixLabors
{
public interface ISixLaborsExtensions
{
/// <summary>
/// 生成会员证书
/// </summary>
/// <param name="numX"></param>
/// <param name="numY"></param>
/// <param name="nameX"></param>
/// <param name="nameY"></param>
/// <param name="yearX"></param>
/// <param name="yearY"></param>
/// <param name="mounthX"></param>
/// <param name="mounthY"></param>
/// <param name="DayX"></param>
/// <param name="DayY"></param>
/// <returns></returns>
Task<SixLaborOptions> GenerateMembershipCertificateAsync(string companyName, string orderNo, bool isAdd = true, int numX = 700, int numY = 560, int nameX = 540, int nameY = 665, int yearX = 1488, int yearY = 1155,
int mounthX = 1612, int mounthY = 1155, int DayX = 1706, int DayY = 1155);
}
}
SixLaborsExtensions.cs
using Org.BouncyCastle.Asn1;
using SixLabors.Fonts;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Drawing.Processing;
using SixLabors.ImageSharp.Processing;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Tzkj.Core.Constants;
using Tzkj.Core.System;
using Volo.Abp.DependencyInjection;namespace Tzkj.SixLabors
{
public class SixLaborsExtensions : ISixLaborsExtensions, IScopedDependency
{
private readonly FontCollection _fontCollection;public SixLaborsExtensions(FontCollection fontCollection)
{
_fontCollection = fontCollection;
}
/// <summary>
/// 生成会员证书
/// <paramref name="companyName">名称</param>
/// <param name="numX"></param>
/// <param name="numY"></param>
/// <param name="nameX"></param>
/// <param name="nameY"></param>
/// <param name="yearX"></param>
/// <param name="yearY"></param>
/// <param name="mounthX"></param>
/// <param name="mounthY"></param>
/// <param name="DayX"></param>
/// <param name="DayY"></param>
/// <returns></returns>
public async Task<SixLaborOptions> GenerateMembershipCertificateAsync(string companyName, string orderNo,
bool isAdd = true,
int numX = 700, int numY = 560, int nameX = 540, int nameY = 665, int yearX = 1488, int yearY = 1155,
int mounthX = 1612, int mounthY = 1155, int DayX = 1706, int DayY = 1155)
{
using var img = await Image.LoadAsync("wwwroot/robotMember.jpg");
_fontCollection.TryGet("FangSong", out FontFamily fontFamily);
string? numberNo = orderNo;
using var img2 = img.Clone(ctx => ApplyScalingWaterMarkRobot(ctx, fontFamily, Color.Black,
companyName, orderNo, isAdd, out numberNo, numX, numY, nameX, nameY, yearX, yearY, mounthX, mounthY, DayX, DayY));
using var memoryStream = new MemoryStream();
await img2.SaveAsJpegAsync(memoryStream);
var tt = memoryStream.ToArray();return new SixLaborOptions
{
ImgBytes = tt,
CertificateNo = numberNo
};
}private IImageProcessingContext ApplyScalingWaterMarkRobot(IImageProcessingContext processingContext,
FontFamily fontFamily, Color color, string companyName, string orderNo, bool isAdd, out string numberNo, int numX = 494, int numY = 528, int nameX = 450, int nameY = 650, int yearX = 650, int yearY = 736,
int mounthX = 896, int mounthY = 736, int DayX = 990, int DayY = 736)
{
var numPoint = new PointF(numX, numY);
Font numFont = fontFamily.CreateFont(38);
var numTextOptions = new RichTextOptions(numFont)
{
Origin = numPoint
};
//processingContext.DrawText(numTextOptions, "HRES20231225001", color);
numberNo = orderNo;
if (isAdd)
{//参考地址:C# 生成订单号-CSDN博客
numberNo = GenerateOrderNo.Gener(orderNo,SystemConstants.MemberCardPrefix);
}processingContext.DrawText(numTextOptions, numberNo, color);
var namePoint = new PointF(nameX, nameY);
Font nameFont = fontFamily.CreateFont(48);
var nameTextOptions = new RichTextOptions(nameFont)
{
Origin = namePoint
};
processingContext.DrawText(nameTextOptions, companyName, color);var yearPoint = new PointF(yearX, yearY);
var monthPoint = new PointF(mounthX, mounthY);
var dayPoint = new PointF(DayX, DayY);
Font dateFont = fontFamily.CreateFont(38);processingContext
.DrawText(
new RichTextOptions(dateFont)
{
Origin = yearPoint
},
"2023",
color)
.DrawText(
new RichTextOptions(dateFont)
{
Origin = monthPoint
},
"06",
color)
.DrawText(
new RichTextOptions(dateFont)
{
Origin = dayPoint
},
"26",
color);return processingContext;
}
}
}
SixLaborsModule.cs
using Microsoft.Extensions.DependencyInjection;
using SixLabors.Fonts;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.Modularity;namespace Tzkj.SixLabors
{
public class SixLaborsModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
//var configuration = context.Services.GetConfiguration();//图片合成组件单例注入
context.Services.AddSingleton<FontCollection>(serviceProvider =>
{
FontCollection fontCollection = new();
fontCollection.Add("./wwwroot/Fonts/simfang.ttf");
//fontCollection.Add(configuration["SixLabors:FontsPath"]);
return fontCollection;
});
}
}
}
SixLaborOptions.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace Tzkj.SixLabors
{
public class SixLaborOptions
{
/// <summary>
/// 证书编号
/// </summary>
public string CertificateNo { get; set; }/// <summary>
/// 二进制图片
/// </summary>
public byte[] ImgBytes { get; set; }
}
}
controller.cs
/// <summary>
/// 获取会员证书
/// </summary>
/// <param name="id">企业id</param>
/// <returns></returns>
[HttpGet("get-memberCard")]
public async Task<IActionResult> GetMemberCardUrlAsync(Guid id)
{
byte[] bytes = await _companyInfoService.GetMemberCardUrlAsync(id);
var qualification = File(bytes, "image/jpeg");return qualification;
}