C#使用Graphics合成二维码和头像的分享图(小程序分享、App分享)-C/S开发框架
适用于微信小程序分享图、app分享图
//分享的海报背景图片 使用本地图片文件
string path = Server.MapPath("/Content/images/backimg.jpg");
Image imgSrc = Image.FromFile(path); //将文件加载成图片格式
//二维码图片文件 使用远程图片文件
var qr_url="http://xxxxxx:8001/Images/qrimg.jpg";
Image qrCodeImage= ReduceImage(qr_url, 122, 122);
//头像文件 使用远程图片文件
var headurl="http://xxxxxx:8001/Images/header.jpg";
Image headImage= ReduceImage(headurl, 59, 59);
//开始合成图片 声明画图工具
using (Graphics g = Graphics.FromImage(imgSrc))
{
//画推广二维码 声明起始坐标点
//从x轴30像素处、y轴的40像素处开始画
int qr_x = 30,qr_y = 40;
//指定二维码在合成图上显示的坐标和区域大小
Rectangle destRect = new Rectangle(qr_x, qr_y, qrCodeImage.Width, qrCodeImage.Height);
//在destRect声明的区域内,开始绘制二维码
Rectangle srcRect = new Rectangle(0, 0, qrCodeImage.Width, qrCodeImage.Height);
//开始绘制 GraphicsUnit.Pixel 表示以像素为单位
g.DrawImage(qrCodeImage, destRect, srcRect, GraphicsUnit.Pixel);
//画头像 裁剪头像(圆形)
Image header = CutEllipse(titleImage, new Size(59, 59));
int w = header.Width, h = header.Height; //图片宽高
int x = 24, y = 982; //图片坐标
g.DrawImage(header,
new Rectangle(x, y, w, h),
new Rectangle(0, 0, w, h),
GraphicsUnit.Pixel);
//画昵称 思源黑体 CN 常规 字体大小18 粗体
Font font = new Font("Source Han Sans CN Regular", 18, FontStyle.Bold, GraphicsUnit.Pixel);
Color fontColor = (Color)new ColorConverter().ConvertFromString("#999999");
g.DrawString("张三", font, new SolidBrush(fontColor), 100, 990); //坐标点 x=100 y=990
//画其他文本 思源黑体 CN 常规
var othertext = "邀请您看直播";
g.DrawString(othertext, font, new SolidBrush(fontColor), 101, 1014); //坐标点 x=100 y=990
header.Dispose();
g.Dispose();
}
//获取系统编码类型数组,包含了jpeg,bmp,png,gif,tiff
long quality = 80L; //图像质量 1 - 100的范围 图片的质量决定了生成图片后的文件大小
ImageCodecInfo[] icis = ImageCodecInfo.GetImageEncoders();
ImageCodecInfo ici = GetEncoder(ImageFormat.Jpeg);
EncoderParameters ep = new EncoderParameters(1);
ep.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, quality);
//将图片转换成二进制流
MemoryStream ms = new MemoryStream();//读取字节流
imgSrc.Save(ms, ici, ep);
var buffer = ms.GetBuffer(); //图片流
ms.Dispose();
imgSrc.Dispose();
qrCodeImage.Dispose();
headImage.Dispose();
ep.Dispose();
GetEncoder 方法用于返回图片的格式,这里设置的为jpeg格式
private static ImageCodecInfo GetEncoder(ImageFormat format)
{
ImageCodecInfo[] codecs = ImageCodecInfo.GetImageDecoders();
foreach (ImageCodecInfo codec in codecs)
{
if (codec.FormatID == format.Guid)
{
return codec;
}
}
return null;
}
ReduceImage 方法可以缩放图片大小
/// <summary>
/// 缩小/放大图片
/// </summary>
/// <param name="url">图片网络地址</param>
/// <param name="toWidth">缩小/放大宽度</param>
/// <param name="toHeight">缩小/放大高度</param>
/// <returns></returns>
private static Image ReduceImage(string url, int toWidth, int toHeight, string param = null)
{
try
{
Stream responseStream = null;
if (param != null) //post请求
{
var intResult = HttpHelper.HttpClientPost(url, param, out responseStream);
}
else
{
WebRequest request = WebRequest.Create(url);
WebResponse response = request.GetResponse();
responseStream = response.GetResponseStream();
}
if (responseStream == null)
{
return null;
}
Image originalImage = Image.FromStream(responseStream);
if (toWidth <= 0 && toHeight <= 0) //返回原图
{
return originalImage;
}
else if (toWidth > 0 && toHeight > 0) ////给了宽*高 如果原始小,则返回原图
{
if (originalImage.Width < toWidth && originalImage.Height < toHeight)
return originalImage;
}
else if (toWidth <= 0 && toHeight > 0) //给了高,根据高计算宽,得出正方形图片
{
if (originalImage.Height < toHeight)
return originalImage;
toWidth = originalImage.Width * toHeight / originalImage.Height;
}
else if (toHeight <= 0 && toWidth > 0) //给了宽,根据宽计算高,得出正方形图片
{
if (originalImage.Width < toWidth)
return originalImage;
toHeight = originalImage.Height * toWidth / originalImage.Width;
}
Image toBitmap = new Bitmap(toWidth, toHeight); //定义一个指定大小的画布背景
using (Graphics g = Graphics.FromImage(toBitmap)) //定义画图工具,使用画图工具加载画布背景,开始在画布上作图
{
//图片缩放时使用
g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighSpeed; //高速度、低质量
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; //图像缩放质量
//生成图片时使用
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; //图片呈现质量,即消除锯齿
g.Clear(Color.Transparent); //清除背景色,并设置颜色为透明 Color.Transparent
g.DrawImage(originalImage,
new Rectangle(0, 0, toWidth, toHeight),
new Rectangle(0, 0, originalImage.Width, originalImage.Height),
GraphicsUnit.Pixel);
originalImage.Dispose();
responseStream.Dispose();
g.Dispose();
return toBitmap;
}
}
catch (Exception ex)
{
throw;
}
}
CutEllipse方法用来裁剪头像
/// <summary>
/// 画圆形头像
/// </summary>
/// <param name="img">待裁剪的图片</param>
/// <param name="size">裁剪大小</param>
/// <returns></returns>
private static Image CutEllipse(Image img, Size size)
{
try
{
var rec = new Rectangle(0, 0, size.Width, size.Height); //声明位置和大小
Bitmap bitmap = new Bitmap(size.Width, size.Height); //声明画布并指定大小
Pen p = new Pen(Color.Transparent); //声明透明色画笔
using (Graphics g = Graphics.FromImage(bitmap))
{
using (TextureBrush br = new TextureBrush(img, rec)) //声明画刷
{
g.SmoothingMode = SmoothingMode.HighQuality; //使绘图质量最高,即消除锯齿
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.CompositingQuality = CompositingQuality.HighQuality;
g.FillEllipse(br, rec); //根据指定大小和位置填充圆形
g.DrawEllipse(p, rec); //画圆形图
br.Dispose();
}
g.Dispose();
}
return bitmap;
}
catch (Exception ex)
{
throw;
}
}
接下来开始测试:
后端返回图片方式1: 服务端以 Response.BinaryWrite(buffer) 格式输出到前端
/// <summary>
/// 后端以二进制格式输出到页面
/// </summary>
/// <returns></returns>
[HttpPost]
public ActionResult DrawImages()
{
try
{
string pathparam = "123";
byte[] buffer = null;
DrawShareImage(pathparam, out buffer);
Response.ClearContent();
Response.ContentType = "image/jpeg";
Response.BinaryWrite(buffer);
}
catch (Exception)
{
throw;
}
return View();
}
前端接收方式:原本想使用Ajax的方式请求,结果发现数据格式不支持,遂改用以下方式接收
//方式1
var xhr = new XMLHttpRequest();
xhr.open('POST', apihost + '/Test/DrawImages', true);
xhr.responseType = 'blob';
xhr.setRequestHeader("client_type", "DESKTOP_WEB");
xhr.onload = function () {
if (this.status === 200) {
var blob = this.response;
var imageUrl = window.URL.createObjectURL(blob);;
$("#showimg").attr('src', imageUrl);
}
}
xhr.send();
//方式2
var xhr = new XMLHttpRequest();
xhr.open('POST', apihost + '/Test/DrawImages', true);
xhr.responseType = 'arraybuffer';
xhr.setRequestHeader("client_type", "DESKTOP_WEB");
xhr.onload = function () {
if (this.status === 200) {
var blob = this.response;
let bytes = new Uint8Array(blob);
let data = "";
let len = bytes.byteLength;
for (let i = 0; i < len; i++) {
data += String.fromCharCode(bytes[i]);
}
var imageUrl = "data:image/jpeg;base64," + window.btoa(data);
$("#showimg").attr('src', imageUrl);
}
}
xhr.send();
后端返回图片方式2: 服务端以 FileContentResult(buffer) 格式输出到前端,前端请求方式同上
/// <summary>
/// 后端以文件流格式输出到页面
/// </summary>
/// <returns></returns>
[HttpPost]
public FileResult DrawImages()
{
try
{
string pathparam = "123";
byte[] buffer = null;
DrawShareImage(pathparam, out buffer);
//Response.ClearContent();
//Response.ContentType = "image/jpeg";
//Response.BinaryWrite(buffer);
return new FileContentResult(buffer, "image/jpeg");
}
catch (Exception)
{
throw;
}
}
后端返回图片方式3: 服务端以 Base64字符串格式输出到前端,前端可以使用Ajax方式请求
/// <summary>
/// 后端以Base64格式输出到页面
/// </summary>
/// <returns></returns>
[HttpPost]
public string DrawImages()
{
try
{
string pathparam = "123";
byte[] buffer = null;
DrawShareImage(pathparam, out buffer);
return Convert.ToBase64String(buffer);
}
catch (Exception ex)
{
throw;
}
}
前端请求Base64格式图片
//方法1
var xhr = new XMLHttpRequest();
xhr.open('POST', apihost + '/Test/DrawImages', true);
xhr.responseType = 'text'; //"" | "arraybuffer" | "blob" | "document" | "json" | "text"
xhr.setRequestHeader("client_type", "DESKTOP_WEB");
xhr.onload = function () {
if (this.status === 200) {
var content = this.response;
var imageUrl = "data:image/jepg;base64," + content;
$("#showimg").attr('src', imageUrl);
}
}
xhr.send();
//方法2
$.ajax({
type: "POST",//方法类型
dataType: "text", //服务器返回的数据类型
url: apihost + "/Test/DrawImages",//url
data: {}, //jQuery的serialize()方法通过序列化表单值
success: function (result) {
var imageUrl = "data:image/jepg;base64," + result;
$("#showimg").attr('src', imageUrl);
},
error: function (s) {
alert("异常!");
}
});
效果图:
CSCODE.NETC/S开发框架-C/S框架网专注.NET技术、C/S架构快速开发框架软件