安装包
SixLabors.ImageSharp.Drawing 2.0
需要的字体:宋体和微软雅黑 商用的需要授权如果商业使用可以使用方正书宋、方正黑体,他们可以免费商用
方正官网
代码
using SixLabors.Fonts;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Drawing;
using SixLabors.ImageSharp.Drawing.Processing;
using SixLabors.ImageSharp.Formats.Png;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
namespace CreatePosterStu01
{
internal class Program
{
static async Task Main(string[] args)
{
//画布宽度
int canvasWidth = 750;
//画布高度
int canvasHeight = 1096;
//素材的宽度
int posterWidth = 670;
//素材的高度
int posterHeight = 810;
//二维码宽度
int qrCodeWidth = 140;
//二维码高度
int qrCodeHeight = 140;
//头像宽度和高度
int avatorWidth = 110;
int avatorHeight = 110;
//昵称
var nickName = "假装wo不帅";
//签名,个性签名
var diySign = "\"这个真不错,推荐你也来看看啊啊啊sdf\"";
var imgName = $"{DateTime.Now.ToString("yyyy_MM_dd_HH_mm_ss")}.png";
using (Image<Rgba32> image = new Image<Rgba32>(canvasWidth, canvasHeight, Color.White))
{
//绘制顶部图片
var topImage = Image.Load("images/main.jpg");
//也可以加载stream
//var qrCodeImage = Image.Load(data);
//改变显示区域的大小,并不能改变图片大小
//var posterRect = new Rectangle(0,0, posterWidth, posterHeight);
//image.Mutate(t => t.DrawImage(topImage, new Point(40, 40), posterRect, 1f));
//存放海报位置
//KnownResamplers.Bicubic 获取实现双三次核算法W(x)的双三次采样器
//KnownResamplers.Box 获取实现盒算法的盒采样器。类似于升级时的最近邻居。缩小像素时,会对像素进行平均,将像素合并在一起。
topImage.Mutate(x => x.Resize(posterWidth, posterHeight, KnownResamplers.Box));
image.Mutate(t => t.DrawImage(topImage, new Point(40, 40), 1f));
//存放二维码
var qrcodeImage = Image.Load("images/qrcode.jpg");
qrcodeImage.Mutate(x => x.Resize(qrCodeWidth, qrCodeHeight, KnownResamplers.Box));
image.Mutate(t => t.DrawImage(qrcodeImage, new Point(560, 900), 1f));
//存放头像
var avatorImage = Image.Load("images/avator.jpg");
//转化为圆角,此时有黑色边框
avatorImage.Mutate(x => x.Resize(avatorWidth, avatorHeight));
//avatorImage.Mutate(x => x.ConvertToAvatar(new Size(avatorWidth, avatorHeight), (avatorWidth / 2.0f)));
image.Mutate(t => t.DrawImage(avatorImage, new Point(40, 915), 1f));
//显示昵称
FontCollection fonts = new FontCollection();
var songtiFamily = fonts.Add("fonts/simsun.ttf");
var yaheiFamily = fonts.Add("fonts/weiruanyahei.ttf");
image.Mutate(t => t.DrawText(nickName, new Font(yaheiFamily, 15 * 2, FontStyle.Bold), Color.ParseHex("#000000"), new PointF(160, 940)));
//显示签名
//判断长度决定是否显示...,目前一行最多16个字,超出部分显示...
if (diySign.Length > 16)
{
diySign = diySign.Remove(15, diySign.Length - 15) + "...";
}
image.Mutate(t => t.DrawText(diySign, new Font(yaheiFamily, 13 * 2, FontStyle.Bold), Color.ParseHex("#cccccc"), new PointF(160, 985)));
var fileStream = File.Create(imgName);
await image.SaveAsync(fileStream, new PngEncoder());
//也可以保存为文件流,web端使用
/*
using (var stream = new MemoryStream())
{
await image.SaveAsync(stream, new PngEncoder());
stream.Position = 0;
return stream;
}
*/
}
await Console.Out.WriteLineAsync("完成~~");
}
}
/// <summary>
/// https://github.com/SixLabors/Samples/blob/main/ImageSharp/AvatarWithRoundedCorner/Program.cs
/// </summary>
public static class Helper
{
// Implements a full image mutating pipeline operating on IImageProcessingContext
public static IImageProcessingContext ConvertToAvatar(this IImageProcessingContext context, Size size, float cornerRadius)
{
return context.Resize(new ResizeOptions
{
Size = size,
Mode = ResizeMode.Crop
}).ApplyRoundedCorners(cornerRadius);
}
// This method can be seen as an inline implementation of an `IImageProcessor`:
// (The combination of `IImageOperations.Apply()` + this could be replaced with an `IImageProcessor`)
private static IImageProcessingContext ApplyRoundedCorners(this IImageProcessingContext context, float cornerRadius)
{
Size size = context.GetCurrentSize();
IPathCollection corners = BuildCorners(size.Width, size.Height, cornerRadius);
context.SetGraphicsOptions(new GraphicsOptions()
{
Antialias = true,
// Enforces that any part of this shape that has color is punched out of the background
//强制将此形状中任何有颜色的部分从背景中冲压出来
AlphaCompositionMode = PixelAlphaCompositionMode.DestOut
});
// Mutating in here as we already have a cloned original
// use any color (not Transparent), so the corners will be clipped
//在这里突变,因为我们已经有了一个克隆的原始使用任何颜色(非透明),所以角将被剪切
foreach (IPath path in corners)
{
context = context.Fill(Color.Red, path);
}
return context;
}
private static IPathCollection BuildCorners(int imageWidth, int imageHeight, float cornerRadius)
{
// First create a square
var rect = new RectangularPolygon(-0.5f, -0.5f, cornerRadius, cornerRadius);
// Then cut out of the square a circle so we are left with a corner
IPath cornerTopLeft = rect.Clip(new EllipsePolygon(cornerRadius - 0.5f, cornerRadius - 0.5f, cornerRadius));
// Corner is now a corner shape positions top left
// let's make 3 more positioned correctly, we can do that by translating the original around the center of the image.
float rightPos = imageWidth - cornerTopLeft.Bounds.Width + 1;
float bottomPos = imageHeight - cornerTopLeft.Bounds.Height + 1;
// Move it across the width of the image - the width of the shape
IPath cornerTopRight = cornerTopLeft.RotateDegree(90).Translate(rightPos, 0);
IPath cornerBottomLeft = cornerTopLeft.RotateDegree(-90).Translate(0, bottomPos);
IPath cornerBottomRight = cornerTopLeft.RotateDegree(180).Translate(rightPos, bottomPos);
return new PathCollection(cornerTopLeft, cornerBottomLeft, cornerTopRight, cornerBottomRight);
}
}
}