You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

二维码需放大近距离才可读取的问题解决及性能优化咨询

二维码读取困难的解决方案与优化建议

一、解决"需放大近距离读取"的核心问题

这种情况主要源于二维码模块尺寸不足、遮挡过度或对比度不够,针对性调整即可解决:

  • 增大模块像素尺寸:代码中GetGraphic(30, ...)的第一个参数是每个二维码模块(黑白小方块)的像素数,当前设为30,若识别困难可上调至40-50(需平衡二维码整体大小),模块越大,远距离识别的成功率越高。
  • 修正logo遮挡逻辑:当前手动将logo固定resize为300x300后直接绘制,会无视二维码大小过度遮挡关键模块。改用GetGraphic内置的icon参数,让库自动处理logo的大小和位置,避开定位区域。
  • 强化对比度:确保深色模块(传入的color参数)和白色背景的色差足够大,避免使用浅灰、淡色等相近配色,模糊的边界会大幅降低识别效率。

二、调整二维码特性实现快速读取

  • 保持低纠错等级:当前使用的L级(最低纠错)是最优选择,L级能容纳更多数据且模块数量最少,识别速度最快。除非需要强容错场景,不要切换到M/Q/H级,否则二维码版本升高,模块密度增加,识别难度陡增。
  • 强制指定低版本(数据量允许时):代码中requestedVersion设为-1会自动计算版本,若数据量小,直接指定版本1-5,固定模块数量,避免因自动升级导致模块过密。
  • 保留安静区:代码中drawQuietZones设为true,务必保持这个设置——安静区是二维码周围的空白区域,是识别器定位的关键,去掉后识别率会暴跌。

三、提升二维码读取速度的方法

  • 生成无损格式:代码中已使用PNG格式,继续保持,不要用JPG压缩,JPG的模糊边缘会让识别器难以区分模块。
  • 精简数据量:如果P_ENC_Text的内容可以压缩(比如缩短加密字符串、使用更高效的编码方式,数字/字母编码比UTF-8更节省空间),模块数量减少后,识别速度自然提升。
  • 读取端预处理优化:如果是自研读取功能,增加图像预处理步骤:自动调整亮度对比度、二值化处理、防抖去模糊,这些能让识别器更快锁定二维码。

四、大幅提升读取性能的代码优化建议

替换手动绘制logo的逻辑,改用库内置的参数,自动避开关键模块:

// 替换原手动绘制logo的代码段
var LogoFilePath = Path.Combine(HttpContext.Current.Server.MapPath("~/assets/images/"), ImageName);
// 直接传入logo,设置占比15%,库会自动处理位置和大小
Bitmap bitmap = qrCode.GetGraphic(30, color, Color.White, new Bitmap(LogoFilePath), 15);

2. 强制指定二维码版本

如果数据量小,在创建二维码时固定版本:

// 指定版本3,根据实际数据量调整
using (QRCodeData qrCodeData = qrGenerator.CreateQrCode(P_ENC_Text, eccLevel, requestedVersion: 3))

3. 动态调整logo大小

若坚持手动绘制logo,不要固定尺寸,按二维码比例计算最大允许大小:

Bitmap logo = new Bitmap(LogoFilePath);
// logo最大占二维码宽度的15%
int maxLogoSize = (int)(bitmap.Width * 0.15);
logo = Common.ResizeBitmap(logo, maxLogoSize, maxLogoSize);

原始生成代码

public static string RenderQrCodeNewTruckerLogo(string P_ENC_Text, Color color, string GovName)
{
    string ImageName = "NewTruckerLogo.png";
    
    string level = "L";//comboBoxECC.SelectedItem.ToString();
    QRCodeGenerator.ECCLevel eccLevel = (QRCodeGenerator.ECCLevel)(level == "L" ? 0 : level == "M" ? 1 : level == "Q" ? 2 : 3);
    using (QRCodeGenerator qrGenerator = new QRCodeGenerator())
    {
        using (QRCodeData qrCodeData = qrGenerator.CreateQrCode(P_ENC_Text, eccLevel))
        {
            using (QRCode qrCode = new QRCode(qrCodeData))
            {
                MemoryStream ms = new MemoryStream();
                //Bitmap bitmap = qrCode.GetGraphic(20, color, Color.White,
                //    null, 15);
                Bitmap bitmap = qrCode.GetGraphic(30, color, Color.White,
                    null, 15);
                var LogoFilePath = Path.Combine(HttpContext.Current.Server.MapPath("~/assets/images/"), ImageName);
                //var logoImg = Image.FromFile(LogoFilePath);
                Bitmap logo = new Bitmap(LogoFilePath);
                logo = Common.ResizeBitmap(logo, 300, 300);
                Graphics g = Graphics.FromImage(bitmap);
                g.DrawImage(logo, new Point((bitmap.Width - logo.Width) / 2, (bitmap.Height - logo.Height) / 2));
                bitmap.Save(ms, ImageFormat.Png);
                var base64Data = Convert.ToBase64String(ms.ToArray());
            
                string Src = "data:image/png;base64," + base64Data;
                return Src;

            }
        }
    }
}
public QRCodeData CreateQrCode(string plainText, ECCLevel eccLevel, bool forceUtf8 = false, bool utf8BOM = false, EciMode eciMode = EciMode.Default, int requestedVersion = -1)
{
    return GenerateQrCode(plainText, eccLevel, forceUtf8, utf8BOM, eciMode, requestedVersion);
}
public static QRCodeData GenerateQrCode(string plainText, ECCLevel eccLevel, bool forceUtf8 = false, bool utf8BOM = false, EciMode eciMode = EciMode.Default, int requestedVersion = -1)
{
    EncodingMode encoding = GetEncodingFromPlaintext(plainText, forceUtf8);
    var codedText = PlainTextToBinary(plainText, encoding, eciMode, utf8BOM, forceUtf8);
    var dataInputLength = GetDataLength(encoding, plainText, codedText, forceUtf8);
    int version = requestedVersion;
    if (version == -1)
    {
        version = GetVersion(dataInputLength, encoding, eccLevel);
    }

    string modeIndicator = String.Empty;
    if (eciMode != EciMode.Default)
    {
        modeIndicator = DecToBin((int)EncodingMode.ECI, 4);
        modeIndicator += DecToBin((int)eciMode, 8);
    }
    modeIndicator += DecToBin((int)encoding, 4);
    var countIndicator = DecToBin(dataInputLength, GetCountIndicatorLength(version, encoding));
    var bitString = modeIndicator + countIndicator;

    bitString += codedText;

    return GenerateQrCode(bitString, eccLevel, version);
}
public static Bitmap ResizeBitmap(Bitmap bmp, int width, int height)
{
    Bitmap result = new Bitmap(width, height);
    using (Graphics g = Graphics.FromImage(result))
    {
        g.DrawImage(bmp, 0, 0, width, height);
    }

    return result;
}
public Bitmap GetGraphic(int pixelsPerModule, Color darkColor, Color lightColor, Bitmap icon=null, int iconSizePercent=15, int iconBorderWidth = 6, bool drawQuietZones = true)
{
    var size = (this.QrCodeData.ModuleMatrix.Count - (drawQuietZones ? 0 : 8)) * pixelsPerModule;
    var offset = drawQuietZones ? 0 : 4 * pixelsPerModule;

    var bmp = new Bitmap(size, size, System.Drawing.Imaging.PixelFormat.Format32bppArgb);

    using (var gfx = Graphics.FromImage(bmp))
    using (var lightBrush = new SolidBrush(lightColor))
    using (var darkBrush = new SolidBrush(darkColor))
    {
        gfx.InterpolationMode = InterpolationMode.HighQualityBicubic;
        gfx.CompositingQuality = CompositingQuality.HighQuality;
        gfx.Clear(lightColor);

        var drawIconFlag = icon != null && iconSizePercent > 0 && iconSizePercent <= 100;

        GraphicsPath iconPath = null;
        float iconDestWidth = 0, iconDestHeight = 0, iconX = 0, iconY = 0;

        if (drawIconFlag)
        {
            iconDestWidth = iconSizePercent * bmp.Width / 100f;
            iconDestHeight = drawIconFlag ? iconDestWidth * icon.Height / icon.Width : 0;
            iconX = (bmp.Width - iconDestWidth) / 2;
            iconY = (bmp.Height - iconDestHeight) / 2;

            var centerDest = new RectangleF(iconX - iconBorderWidth, iconY - iconBorderWidth, iconDestWidth + iconBorderWidth * 2, iconDestHeight + iconBorderWidth * 2);
            iconPath = this.CreateRoundedRectanglePath(centerDest, iconBorderWidth * 2);
        }

        for (var x = 0; x < size + offset; x = x + pixelsPerModule)
        {
            for (var y = 0; y < size + offset; y = y + pixelsPerModule)
            {
                var module = this.QrCodeData.ModuleMatrix[(y + pixelsPerModule) / pixelsPerModule - 1][(x + pixelsPerModule) / pixelsPerModule - 1];

                if (module)
                {
                    var r = new Rectangle(x - offset, y - offset, pixelsPerModule, pixelsPerModule);

                    if (drawIconFlag)
                    {
                        var region = new Region(r);
                        region.Exclude(iconPath);
                        gfx.FillRegion(darkBrush, region);
                    }
                    else
                    {
                        gfx.FillRectangle(darkBrush, r);
                    }
                }
                else
                {
                    gfx.FillRectangle(lightBrush, new Rectangle(x - offset, y - offset, pixelsPerModule, pixelsPerModule));
                }
            }
        }

        if (drawIconFlag)
        {
            var iconDestRect = new RectangleF(iconX, iconY, iconDestWidth, iconDestHeight);
            gfx.DrawImage(icon, iconDestRect, new RectangleF(0, 0, icon.Width, icon.Height), GraphicsUnit.Pixel);
        }

        gfx.Save();
    }

    return bmp;
}

内容的提问来源于stack exchange,提问作者ahmed salah abd elaziz elbarba

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 20:57:04