C# 使用 QRCode 库生成带中心 Logo 的二维码

小岛来信
小岛来信
发布时间:2026-10-14 | 3人浏览过
原创

在使用 .NET 开发应用时,有时需要生成带有品牌 Logo 或特定图像的二维码。本文演示了如何结合 ThoughtWorks.QRCode 组件与系统自带的 System.Drawing 图形处理能力,创建一个自定义的 HttpHandler (ASHX) 来动态生成“带图二维码”。核心流程包括:生成标准二维码底图 → 读取并缩放 Logo 图片 → 将 Logo 居中绘制到底图上 → 输出结果。

实现原理与目标

标准的二维码虽然可读性强,但缺乏品牌辨识度。我们的目标是生成一张中间嵌有指定图片(如企业 Logo)的二维码。实现步骤如下:

  1. 生成底图:使用 QRCode 编码器将文本转换为黑白位图。
  2. 处理 Logo:读取指定的 Logo 文件,若尺寸不符则按比例缩放为固定尺寸(本例中为 65x65 像素)。
  3. 图层合并:创建一个 Graphics 对象,先在底图上绘制自身(保持背景),再将缩放后的 Logo 计算居中坐标后绘制上去。
  4. 输出响应:将最终合成的图像以 PNG 格式写入 HTTP 响应流。

准备条件

在开始编码前,请确保项目满足以下条件:

  • 开发环境:Visual Studio,支持 ASP.NET WebForms 或 MVC 项目。
  • 第三方库:ThoughtWorks.QRCode。需通过 NuGet 包管理器安装该库,以便引用 QRCodeEncoder 类。
  • GDI+ 依赖:代码使用了 System.Drawing 命名空间。请注意,微软已宣布在 .NET Core/.NET 5+ 中移除对 Desktop GDI+ 的支持。若在现代 .NET Core 项目中运行,建议迁移至 ImageSharp 或 SkiaSharp 等跨平台库。本示例基于传统 .NET Framework 编写。

具体操作步骤

第1步:创建一般处理程序 (ASHX)

为了动态生成二维码,我们创建一个继承自 IHttpHandler 的类。这允许我们在不刷新整个页面的情况下,通过 URL 参数请求生成二维码。

<%@ WebHandler Language="C#" Class="GetQRCode" %>
using System;
using System.Web;
using ThoughtWorks.QRCode.Codec;
using ThoughtWorks.QRCode.Codec.Data;
using ThoughtWorks.QRCode.Codec.Util;
using System.IO;
using System.Text;
using System.Drawing;
using System.Drawing.Drawing2D;

public class GetQRCode : IHttpHandler
{
    // 其他代码...
}

第2步:编写二维码生成逻辑

在 ProcessRequest 方法中,首先从请求中获取待编码的文本数据 (CodeText),然后配置 QRCodeEncoder 参数。关键参数说明:

  • QRCodeEncodeMode: 设置为 BYTE 模式,支持中文及更多字符集。
  • QRCodeScale: 设置放大倍数,值越大二维码越清晰,但文件也越大。
  • QRCodeVersion: 版本限制,设为 8 可控制最大数据容量。
  • QRCodeErrorCorrect: 错误容错等级设为 M (Medium),这是叠加 Logo 所需的最小容错率,否则 Logo 遮挡部分可能导致无法扫描。
String data = context.Request["CodeText"];
if (!string.IsNullOrEmpty(data))
{
    QRCodeEncoder qrCodeEncoder = new QRCodeEncoder();
    qrCodeEncoder.QRCodeEncodeMode = QRCodeEncoder.ENCODE_MODE.BYTE;
    qrCodeEncoder.QRCodeScale = 4;
    qrCodeEncoder.QRCodeVersion = 8;
    qrCodeEncoder.QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.M;
    
    // 1. 生成基础二维码图片
    System.Drawing.Image image = qrCodeEncoder.Encode(data);
    
    // 2. 合并 Logo 并获取最终图像
    Image finalImage = CombinImage(image, context.Server.MapPath("~/images/qr-logo.jpg"));
    
    // 3. 将图像保存到内存流并输出
    using (MemoryStream MStream = new MemoryStream())
    {
        finalImage.Save(MStream, System.Drawing.Imaging.ImageFormat.Png);
        context.Response.ClearContent();
        context.Response.ContentType = "image/png";
        context.Response.BinaryWrite(MStream.ToArray());
        context.Response.Flush();
        context.Response.End();
    }
}

第3步:实现 Logo 叠加函数 (CombinImage)

此函数负责将 Logo 图片居中绘制到二维码底图上。需要注意坐标计算,以确保 Logo 精确位于正中央。

public static Image CombinImage(Image imgBack, string destImg)
{
    // 加载 Logo 图片
    Image img = Image.FromFile(destImg);
    
    // 强制 Logo 尺寸为 65x65 (可根据实际 UI 需求调整)
    if (img.Height != 65 || img.Width != 65)
    {
        img = KiResizeImage(img, 65, 65, 0);
    }
    
    Graphics g = Graphics.FromImage(imgBack);
    
    // 先绘制底图本身 (保留二维码图案)
    g.DrawImage(imgBack, 0, 0, imgBack.Width, imgBack.Height);
    
    // 计算居中位置:(底图宽 - Logo宽) / 2
    int x = imgBack.Width / 2 - img.Width / 2;
    int y = imgBack.Height / 2 - img.Height / 2;
    
    // 绘制 Logo
    g.DrawImage(img, x, y, img.Width, img.Height);
    
    g.Dispose();
    GC.Collect();
    return imgBack;
}

第4步:实现图片缩放函数 (KiResizeImage)

为保证 Logo 美观且不影响扫码,需使用高质量插值算法缩放图片。若原图过大或过小,都需统一缩放到指定尺寸。

public static Image KiResizeImage(Image bmp, int newW, int newH, int Mode)
{
    try
    {
        Image b = new Bitmap(newW, newH);
        Graphics g = Graphics.FromImage(b);
        // 启用高质量双三次插值
        g.InterpolationMode = InterpolationMode.HighQualityBicubic;
        g.SmoothingMode = SmoothingMode.HighQuality;
        g.PixelOffsetMode = PixelOffsetMode.HighQuality;
        g.Clear(Color.Transparent); // 透明背景
        g.DrawImage(bmp, new Rectangle(0, 0, newW, newH), new Rectangle(0, 0, bmp.Width, bmp.Height), GraphicsUnit.Pixel);
        g.Dispose();
        return b;
    }
    catch
    {
        return null;
    }
}

测试与效果

部署上述 Handler 后,可以通过浏览器访问该 ASHX 文件并传递参数进行验证。例如,请求网址:GetQRCode.ashx?CodeText=https://www.example.com。服务器将返回一张生成的 PNG 图片。

上图展示了调用生成的带 Logo 二维码效果。实际使用时,请确保 destImg 指向的图片路径存在且拥有读取权限。此外,由于二维码增加了 Logo 遮挡,建议使用手机 Scanner App 反复测试不同光线下的识别率。

注意事项与维护

  • 资源释放:原文代码中注释掉了 image.Dispose(),但在现代开发中,建议对所有 IDisposable 对象(如 Image, Graphics, MemoryStream)使用 using 语句包裹,以防止内存泄漏。
  • GDI+ 兼容性:如前所述,System.Drawing 是 Windows-only 的 API。如果计划将此代码迁移至 Linux/Docker 环境的 .NET Core 应用中,必须替换为跨平台的图像处理库。
以上就是使用 C# 和 ThoughtWorks.QRCode 生成带中心 Logo 二维码的详细教程,更多关于 ASP.NET 图形处理及二维码技术的资料请关注本站其它相关文章!
相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表