csharp using FileStream fs = File.OpenRead(字体所在目录);
SKTypeface Font = SKTypeface.FromStream(fs);
csharpSKPaint text_paint = new SKPaint
{
TextSize = 24F,
Color = sKColors,
Typeface = Font,
TextScaleX = scale,
FakeBoldText = bold,
IsAntialias = true,//抗锯齿
IsDither = true
};
csharp SKRoundRect roundRect = new SKRoundRect(new SKRect(0, 0, childSurface1Width, childSurface1Height), 11, 11);
SKCanvas对象实例.ClipRoundRect(roundRect);
csharp/// </summary>
/// <param name="canvas">画布</param>
/// <param name="text">多行文字</param>
/// <param name="x">x坐标</param>
/// <param name="y">y坐标</param>
/// <param name="paint">画笔</param>
/// <param name="maxWidth">单行文字最大宽度</param>
/// <param name="maxLines">最大行数,如果超出,则使用...</param>
public static void DrawMuiltLineText(SKCanvas canvas, string text, float x, float y, SKPaint paint, float maxWidth, int maxLines)
{
//已写出行数
int lines = 0;
//省略号宽度
var ellipseWidth = paint.MeasureText("...");
//如果文字没写完且已写行数小于最大行数,则继续写出
while (!string.IsNullOrEmpty(text) && lines < maxLines)
{
//单行文字
string lineStr;
//单行文字长度
long strLength;
//非最后一行
if (lines != maxLines - 1)
{
//调用BreakText方法,可计算指定宽度能写出多少文字
strLength = paint.BreakText(text, maxWidth, out float ww, out lineStr);
}
//最后一行
else
{
//调用BreakText方法计算单行文字长度,这里需减去省略号宽度
strLength = paint.BreakText(text, maxWidth - ellipseWidth, out float ww, out lineStr);
//假如字还没写完,需加省略号
if (strLength < text.Length)
{
lineStr += "...";
}
}
//文字矩形
var tRect = new SKRect();
//计算文字矩形
paint.MeasureText(lineStr, ref tRect);
//计算坐标
var tPoint = new SKPoint
{
X = x - tRect.Left,
//这里注意Y坐标需要加上行高
Y = y + lines * paint.FontSpacing - tRect.Top
};
//写出一行文字
canvas.DrawText(lineStr, tPoint, paint);
//已写出行数加1
lines++;
//取剩余文字
text = text.Substring((int)strLength);
}
}
c#public class 海报生成
{
/// <summary>
/// 自定义字体
/// </summary>
static SKTypeface? Font;
/// <summary>
/// 生成员工活码图片
/// </summary>
/// <param name="bgPath">背景地址</param>
/// <param name="qrPath">二维码地址</param>
/// <param name="title">标题</param>
/// <param name="text">子标题</param>
public static Stream CreateActivityDiyQrCode(string bgPath, string qrPath, string coverPath, string title)
{
if (!File.Exists(bgPath))
throw new Exception($"不存在文件:{bgPath}");
if (Font == null)
{
var fontPath = $"AlibabaPuHuiTi-2-45-Light.ttf";
using (FileStream fs = File.OpenRead(fontPath))
{
Font = SKTypeface.FromStream(fs);
}
}
//字体设置
var text_paint = new SKPaint
{
TextSize = 24F,
Typeface = Font,
FakeBoldText = true,
IsAntialias = true,
IsDither = true
};
// 创建一个主画布
using var bgMap = SKBitmap.Decode(bgPath);
var mapInfo = new SKImageInfo(495, 880);
var map = SKBitmap.FromImage(SKImage.Create(mapInfo));
// 创建一个主画布的画布上下文
using var mainCanvas = new SKCanvas(map);
var bsSize = new SKSizeI(495, 880);
var bgImage = bgMap.Resize(bsSize, SKFilterQuality.High);
mainCanvas.DrawColor(SKColors.White);
mainCanvas.DrawBitmap(bgImage, 0, 0);
//顶部
var coverBitmap = SKBitmap.Decode(coverPath);
mainCanvas.DrawBitmap(coverBitmap, 16, y: 24);
mainCanvas.DrawText(title, 72, 53, text_paint);
//二维码画布
var childSurface1Height = mapInfo.Height - (630 + 20);
var childSurface1Width = mapInfo.Width - (283 + 20);
using var childSurface1 = new SKBitmap(childSurface1Width, childSurface1Height);
using var childCanvas1 = new SKCanvas(childSurface1);
childCanvas1.Clear(SKColors.Transparent);
SKRoundRect roundRect = new SKRoundRect(new SKRect(0, 0, childSurface1Width, childSurface1Height), 11, 11);
childCanvas1.ClipRoundRect(roundRect);
var qrHeight = 160;
var qrWidth = 160;
var qrMap = SKBitmap.Decode(qrPath);
var qrSize = new SKSizeI(qrWidth, height: qrHeight);
var qrImage = qrMap.Resize(qrSize, SKFilterQuality.High);
childCanvas1.DrawColor(SKColors.White);
childCanvas1.DrawBitmap(qrImage, 16, 12);
var qrTextY = 200;
var qrTextX = 35;
childCanvas1.DrawText("扫码加好友", qrTextX, qrTextY, text_paint);
// 把二维码画布画到主画布上
mainCanvas.DrawBitmap(childSurface1, 283, 630);
var stream = SKImage.FromBitmap(map).Encode(SKEncodedImageFormat.Png, 100).AsStream();
return stream;
}
}
string localPath = await "imgUrl".DownloadFileAsync(filePath, $"temp_prodImg_{nowTimeFileName}");
csharpprivate async Task<string> SaveIgmToTemp(string fileName, byte[] byteArray)
{
using MemoryStream imgStream = new MemoryStream(byteArray);
string tempPath = "temp/image/";
string filePath = Path.Combine(tempPath, fileName).Replace("\\", "/");
if (!Directory.Exists(tempPath)) Directory.CreateDirectory(tempPath);
using var fileStream = File.Create(filePath);
imgStream.CopyTo(fileStream);
return filePath;
}
csharppublic class ImageHelper
{
/// <summary>
/// 生成产品二维码海报图
/// </summary>
/// <param name="prodPath">产品图地址(本地地址)</param>
/// <param name="qrCodePath">二维码地址(本地地址)</param>
/// <param name="regularPriceF">产品原价</param>
/// <param name="salePriceF">产品售价</param>
/// <param name="prodTitle">产品标题</param>
/// <param name="marginX">整体的X边距</param>
/// <param name="marginY">整体的Y边距</param>
/// <param name="additionalH">额外增高</param>
/// <param name="fontPath">字体路径(本地地址)</param>
/// <returns></returns>
public static Stream CreateProductQrImage(string prodPath, string qrCodePath, float regularPriceF, float salePriceF, string prodTitle, int marginX = 35, int marginY = 35, int additionalH = 200, string fontPath = "font.ttf")
{
int prodRadius = 11;
//分别获取原价和售价的整数和小数
string salePriceZero = "." + salePriceF.ToString("0.00").Split('.')[1];
string salePriceInt = ((int)salePriceF).ToString();
string regularPriceZero = "." + regularPriceF.ToString("0.00").Split('.')[1];
string regularPriceInt = ((int)regularPriceF).ToString();
SKBitmap prodBitmapSource = SKBitmap.Decode(prodPath);
var bsSize = new SKSizeI(500, 550);
SKBitmap prodBitmap = prodBitmapSource.Resize(bsSize, SKFilterQuality.High);
//根据产品图片大小生成画布大小
using SKBitmap mainBitmap = new SKBitmap(prodBitmap.Width + marginX * 2, prodBitmap.Height + additionalH + marginY * 2);
using SKCanvas mainCanvas = new SKCanvas(mainBitmap);
mainCanvas.Clear();
mainCanvas.DrawColor(SKColors.White);
var prodReBitmap = new SKBitmap(bsSize.Width, bsSize.Height);
using SKCanvas prodCanvas = new SKCanvas(prodReBitmap);
prodCanvas.Clear();
SKRoundRect roundRect = new SKRoundRect(new SKRect(0, 0, bsSize.Width, bsSize.Height), prodRadius, prodRadius);
prodCanvas.ClipRoundRect(roundRect);
prodCanvas.DrawColor(SKColors.White);
prodCanvas.DrawBitmap(prodBitmap, new SKPoint() { X = 0, Y = 0 });
//画产品图
mainCanvas.DrawBitmap(prodReBitmap, marginX, marginY);
//画文字 MeasureText
var line_1Paint = GetSKPaint(fontPath, SKColor.Parse("#af243d"));
string row1_col1Text = "¥";
SKRect row1_col1GapSkRect = new SKRect();
SKRect row1_col2GapSkRect = new SKRect();
SKRect row2_GapSkRect = new SKRect();
SKRect row2_col1GapSkRect = new SKRect();
line_1Paint.MeasureText(text: row1_col1Text, bounds: ref row1_col1GapSkRect);
float row1Y = prodBitmap.Height + prodBitmap.Height / 7;
mainCanvas.DrawText(row1_col1Text, marginX, row1Y, line_1Paint);
float row1X = marginX + row1_col1GapSkRect.Width + row1_col1GapSkRect.Width / 2;
line_1Paint.TextSize = 45F;
mainCanvas.DrawText(salePriceInt, row1X, y: row1Y, line_1Paint);
line_1Paint.MeasureText($"{salePriceInt}", ref row1_col2GapSkRect);
line_1Paint.TextSize = 25F;
row1X = marginX + row1_col2GapSkRect.Width + (row1_col2GapSkRect.Width / 2) + (row1_col2GapSkRect.Width / 7);
mainCanvas.DrawText(salePriceZero, row1X, y: row1Y, line_1Paint);
row1Y = row1Y + row1_col1GapSkRect.Height * 2 + 10;
string line_2Col1Text = $"价格";
SKPaint line_2Patin = GetSKPaint(fontPath, SKColors.Gray, 15F, false);
//画第二行第一段文字
mainCanvas.DrawText(line_2Col1Text, marginX, row1Y, line_2Patin);
//第二行第一段文字(价格)的大小方位
line_2Patin.MeasureText($"{line_2Col1Text}", ref row2_col1GapSkRect);
//画第二行第二段文字
string row2Col2Text = $"¥{regularPriceInt}{regularPriceZero}";
float row2Col2TextStartPoint = marginX + row2_col1GapSkRect.Width + 5;
mainCanvas.DrawText(row2Col2Text, row2Col2TextStartPoint, row1Y, line_2Patin);
line_2Patin.MeasureText(row2Col2Text, ref row2_GapSkRect);
//画线
SKPaint linePaint = new SKPaint
{
Style = SKPaintStyle.Stroke,
Color = SKColors.Gray,
StrokeWidth = 2
};
float lineY = row1Y - row2_GapSkRect.Height * .4f;
mainCanvas.DrawLine(row2Col2TextStartPoint, lineY, row2Col2TextStartPoint + row2_GapSkRect.Width+10, lineY, linePaint);
DrawMuiltLineText(
mainCanvas,
prodTitle,
marginX,
row1Y + row2_GapSkRect.Height + 10,
GetSKPaint(fontPath, SKColor.Parse("#292929"), 25F, bold: false, 1),
prodBitmap.Width / 2 + 10,
2);
using SKBitmap qrCodeBimap = SKBitmap.Decode(qrCodePath);
int wh = 150;
int x = mainBitmap.Width - wh - wh / 5;
int y = mainBitmap.Height - wh - wh / 4;
//画二维码
//using SKImage qrCodeSKImage = SKImage.FromEncodedData(SKData.Create(qrCodePath));
//int x = mainBitmap.Width - 100; //- qrCodeSKImage.Width;
//int y = mainBitmap.Height - 100;// - qrCodeSKImage.Height;
SKRect qrCodeRect = SKRect.Create(x, y, wh, wh);
mainCanvas.DrawBitmap(qrCodeBimap, qrCodeRect);
Stream stream = SKImage.FromBitmap(mainBitmap).Encode(SKEncodedImageFormat.Png, 100).AsStream();
return stream;
}
/// <summary>
/// 获取画笔
/// </summary>
/// <param name="fontPath"></param>
/// <param name="sKColors"></param>
/// <param name="size"></param>
/// <param name="bold"></param>
/// <param name="scale"></param>
/// <returns></returns>
static SKPaint GetSKPaint(string fontPath, SKColor sKColors, float size = 24F, bool bold = true, float scale = 1f)
{
using FileStream fs = File.OpenRead(fontPath);
SKTypeface Font = SKTypeface.FromStream(fs);
//字体设置
SKPaint text_paint = new SKPaint
{
TextSize = 24F,
Color = sKColors,
Typeface = Font,
TextScaleX = scale,
FakeBoldText = bold,
IsAntialias = true,
IsDither = true
};
return text_paint;
}
///<summary>
/// 画多行文本并省略
/// </summary>
/// <param name="canvas">画布</param>
/// <param name="text">多行文字</param>
/// <param name="x">x坐标</param>
/// <param name="y">y坐标</param>
/// <param name="paint">画笔</param>
/// <param name="maxWidth">单行文字最大宽度</param>
/// <param name="maxLines">最大行数,如果超出,则使用...</param>
public static void DrawMuiltLineText(SKCanvas canvas, string text, float x, float y, SKPaint paint, float maxWidth, int maxLines)
{
//已写出行数
int lines = 0;
//省略号宽度
var ellipseWidth = paint.MeasureText("...");
//如果文字没写完且已写行数小于最大行数,则继续写出
while (!string.IsNullOrEmpty(text) && lines < maxLines)
{
//单行文字
string lineStr;
//单行文字长度
long strLength;
//非最后一行
if (lines != maxLines - 1)
{
//调用BreakText方法,可计算指定宽度能写出多少文字
strLength = paint.BreakText(text, maxWidth, out float ww, out lineStr);
}
//最后一行
else
{
//调用BreakText方法计算单行文字长度,这里需减去省略号宽度
strLength = paint.BreakText(text, maxWidth - ellipseWidth, out float ww, out lineStr);
//假如字还没写完,需加省略号
if (strLength < text.Length)
{
lineStr += "...";
}
}
//文字矩形
var tRect = new SKRect();
//计算文字矩形
paint.MeasureText(lineStr, ref tRect);
//计算坐标
var tPoint = new SKPoint
{
X = x - tRect.Left,
//这里注意Y坐标需要加上行高
Y = y + lines * paint.FontSpacing - tRect.Top
};
//写出一行文字
canvas.DrawText(lineStr, tPoint, paint);
//已写出行数加1
lines++;
//取剩余文字
text = text.Substring((int)strLength);
}
}
}
本文作者:宁骑
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 MIT 许可协议。转载请注明出处!