• 生成二维码



    Chapter1 Qt本地生成二维码-第三方库Libqrencode

    原文链接:https://blog.csdn.net/hhy321/article/details/120245679

    一、功能简介

    QR码(全称为快速响应矩阵码;英语:Quick Response Code)是二维条码的一种,于1994年由日本DENSO WAVE公司发明。QR来自英文Quick Response的缩写,即快速反应,因为发明者希望QR码可以让其内容快速被解码。QR码使用四种标准化编码模式(数字,字母数字,字节(二进制)和汉字)来存储数据。QR码最常见于日本,为目前日本最流行的二维空间条码。QR码比较普通条码可以存储更多数据,也无需要像普通条码般在扫描时需要直线对准扫描仪。因此其应用范围已经扩展到包括产品跟踪,物品识别,文档管理,营销等方面。
    在这里插入图片描述
    在这里插入图片描述

    二、本地生成二维码

    1.第三方库Libqrencode
    官网:https://fukuchi.org/works/qrencode/

    Libqrencode 是一个快速紧凑的库,用于在 QR 码符号中编码数据,这是一个 2D 符号系统,可由方便的终端(如带 CCD 的手机)进行扫描。QR 码容量高达 7000 位或 4000 个字符,具有很高的鲁棒性。

    Libqrencode 接受一个字符串或数据块列表,然后在 QR Code 符号中编码为位图数组。当其他 QR 码应用程序生成图像文件时,使用 libqrencode 允许应用程序直接从原始位图数据中呈现 QR 码符号。此库还包含命令行实用程序输出各种格式的 QR 码图像。

    去官网下载源码包,使用最新的稳定版本qrencode-4.1.0,新建一个Qt Widgets Application工程qrcodeDemo,然后执行以下步骤:

    1. 将源码中的config.h.in文件修改成config.h;
    2. 将qrencode源码中的(*.h *.c)加入到工程中(右键添加现有文件);
    3. 在工程的pro文件中添加宏定义DEFINES += HAVE_CONFIG_H;
    4. 在config.h中重新定义 MAJOR_VERSION、MICRO_VERSION、MINOR_VERSION、VERSION,重新定义的方法:找到#undef MAJOR_VERSION位置,在其下面定义#define MAJOR_VERSION 1,其他几个也这么定义;

    在这里插入图片描述
    2.编写Qt程序代码,生成本地二维码
    (1)新建Qt项目工程
    在这里插入图片描述
    (2)将第三方库的代码复制到一个文件夹里,放到上一步新建的项目文件夹里。
    在这里插入图片描述
    在这里插入图片描述
    (3)项目文件.pro 添加设置

    DEFINES += HAVE_CONFIG_H
    INCLUDEPATH += qrcode
    
    • 1
    • 2

    (4)主窗口里添加头文件引用

    #include 
    #include "qrcode/qrencode.h"
    
    • 1
    • 2

    (5)核心代码如下:

    void MainWindow::on_pushButton_local_clicked()
    {
        QString strUrl = ui->textEdit_url->toPlainText();
     
        QRcode *qrcode;
        qrcode = QRcode_encodeString(strUrl.toStdString().c_str(), 2, QR_ECLEVEL_Q, QR_MODE_8, 1);
     
        qint32 temp_width = 500;
        qint32 temp_height = 500;
        qDebug() << "temp_width=" << temp_width << ";temp_height=" << temp_height;
     
        qint32 qrcode_width = qrcode->width > 0 ? qrcode->width : 1;
        double scale_x = (double)temp_width / (double)qrcode_width;
        double scale_y = (double)temp_height / (double)qrcode_width;
     
        int offset = 14;
        QImage mainimg = QImage(temp_width + offset * 2, temp_height + offset * 2, QImage::Format_ARGB32);
        QPainter painter(&mainimg);
        QColor background(Qt::white);
        painter.setBrush(background);
        painter.setPen(Qt::NoPen);
        painter.drawRect(offset, offset, temp_width, temp_height);
        QColor foreground(Qt::black);
        painter.setBrush(foreground);
     
        for (qint32 y = 0; y < qrcode_width; y++)
        {
            for (qint32 x = 0; x < qrcode_width; x++)
            {
                unsigned char b = qrcode->data[y*qrcode_width + x];
                if (b & 0x01)
                {
                    QRectF r(offset + x * scale_x, offset + y * scale_y, scale_x, scale_y);
                    painter.drawRects(&r, 1);
                }
            }
        }
     
        painter.setPen( QColor(0, 0, 255));
        painter.drawText(temp_width/2, temp_height+offset*2-2, strUrl);
        QPixmap mainmap = QPixmap::fromImage(mainimg);
     
        QLabel* m_pQrlabel = new QLabel();
        m_pQrlabel->setWindowFlags(Qt::WindowCloseButtonHint);
        m_pQrlabel->setAttribute(Qt::WA_QuitOnClose, false);
        m_pQrlabel->setPixmap(mainmap);
        m_pQrlabel->setVisible(true);
        m_pQrlabel->setToolTip(strUrl);
        m_pQrlabel->setWindowTitle("本地生成二维码:" + strUrl);
     
        mainmap.save(QCoreApplication::applicationDirPath() + "\\qrcode_local.jpg",Q_NULLPTR, 100);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52

    (6)运行结果显示如下:
    在这里插入图片描述

    三、在线生成二维码

    1.浏览器chrome
    谷歌浏览器chrome自身支持生成二维码了。不需要额外安装插件,已测试。
    在这里插入图片描述

    Chapter2 Qt生成二维码图片方法

    原文链接:https://blog.csdn.net/qq_44675660/article/details/124955291

    QRCode二维码简介

    QR码是日本DENSO WAVE INCORPORATED公司在60年代研发出的一款开放公开的二维码,目前该公司全面公开了QR码的相关标准,不行使就QR码相关的专利权,且大力推广QR码在各行各业的使用,以至目前QR码得到了广泛应用,许多国际标准化组织将其纳入标准。下面介绍一下开发过程中使用QR码可能涉及的主要参数:

    在这里插入图片描述
    二维码的大小:21码元×21码元~177码元×177码元(以每边4码元为单位递增),二维码大小由码的版本决定;二维码所能包含的信息量与码的大小有关。

    QR码的版本:QR码设有1到40的不同版本(种类),每个版本都具备固有的码元结构(码元数)。(码元是指构成QR码的方形黑白点。)“码元结构”是指二维码中的码元数。从版本1(21码元×21码元)开始,在纵向和横向各自以4码元为单位递增,一直到版本40(177码元×177码元)。
    在这里插入图片描述
    QR码纠错等级:QR码具有“纠错功能”。即使编码变脏或破损,也可自动恢复数据。这一“纠错能力”具备4个级别:级别L、级别M、级别Q、级别H,用户可根据使用环境选择相应的级别.

    如何选定QR码版本?

    在这里插入图片描述
    如何选择适合自己的QR码或查看QR码的具体参数和介绍可以参考QR的官网:QRcode.com|DENSO WAVE

    主要方法

    本文主要讲解使用开源的QR code库在Qt程序中生成二维码,其中我们主要用到的是一个开源的QR编码库qrencode。我们可以将qrencode以添加外库的方式提交到工程中使用,也可以将qrencode的源码添加到工程中编译使用,我们采用第二种方法,通过将qrencode的源码移植到我们的Qt程序中实现二维码的显示。

    步骤

    (1) 下载qrencode源码

    我们到OpenPKG Project: Download下载qrencode的开源程序,我下的是qrencode-4.1.1.tar.gz
    在这里插入图片描述

    qrencode下载地址为:OpenPKG Project: Download

    (2) 将qrencode源码移植到工程中

    1)新建一个Qt工程,将qrencode-4.1.1.tar.gz解压后根目录内的所有.c 和.h文件拷贝到Qt工程中。如图所示:
    在这里插入图片描述
    2)将qrencode源码中的config.h.in文件修改成config.h加入工程,将刚刚添加到Qt工程中的qrenc.c文件移出工程,因为该文件是源代码的主函数,与Qt中的相互冲突,将会导致程序异常退出。添加完后工程中是这样子:
    在这里插入图片描述

    (3) 修改移植文件

    1)在QT的.pro文件中添加全局宏定义

    DEFINES += HAVE_CONFIG_H
    
    • 1

    2)在config.h文件末尾重新定义宏

    #define MAJOR_VERSION 1
    #define MICRO_VERSION 1
    #define MINOR_VERSION 1
    #define VERSION 1
    
    • 1
    • 2
    • 3
    • 4

    (4)使用
    我这里是创建了一个继承QWidget的Widget主窗口,在widget.h中添加上如下两句函数声明

    void GenerateQRcode(QString tempstr, QLabel *label);
    void GenerateQRcode(QString tempstr, QLabel *label, const QString &logo, float scale);
    
    • 1
    • 2

    在widget.c中添加了如下程序,这两个程序是重载函数,提供了生成并画出二维码图片的接口,其中第一个函数是单独生成二维码,第二个函数可以在二维码中间添加图片。

    /*trmpst:二维码包含的信息
     * label:显示二维码的QLabel控件
     * */
    void Widget::GenerateQRcode(QString tempstr, QLabel *label)
    {
        QRcode *qrcode; //二维码数据
        //将QString转化为const char * |2-QR码版本为2 | QR_ECLEVEL_Q 容错等级 |QR_MODE_8 八字节数据 |1-区分大小写
        qrcode = QRcode_encodeString(tempstr.toStdString().c_str(), 2, QR_ECLEVEL_Q, QR_MODE_8, 1);
        qint32 temp_width=label->width(); //显示二维码所用的QLabel大小,也是后面显示二维码图片的大小
        qint32 temp_height=label->height();
        qint32 qrcode_width = qrcode->width > 0 ? qrcode->width : 1;    //生成的二维码宽高(正方形的宽度=高度)
        double scale_x = (double)temp_width / (double)qrcode_width; //二维码图片的缩放比例
        double scale_y =(double) temp_height /(double) qrcode_width;
        QImage mainimg=QImage(temp_width,temp_height,QImage::Format_ARGB32);
        QPainter painter(&mainimg);
        QColor background(Qt::white);
        painter.setBrush(background);
        painter.setPen(Qt::NoPen);
        painter.drawRect(0, 0, temp_width, temp_height);
        QColor foreground(Qt::black);
        painter.setBrush(foreground);
        for( qint32 y = 0; y < qrcode_width; y ++)//qrcode->data是一个存了qrcode_width*qrcode_width个数据的一维数组
        {                                         //这里是把这个一维数组以每行qrcode_width个数据,以二维数组的形式表现出来
            for(qint32 x = 0; x < qrcode_width; x++)
            {
                unsigned char b = qrcode->data[y * qrcode_width + x];
                if(b & 0x01)
                {//根据二维码中黑白点(1/0),在QLabel上以缩放比例画出二维码
                    QRectF r(x * scale_x, y * scale_y, scale_x, scale_y);
                    painter.drawRects(&r, 1);
                }
            }
        }
        QPixmap mainmap=QPixmap::fromImage(mainimg);
        label->setPixmap(mainmap);
        label->setVisible(true);
    }
     
    /*trmpst:二维码包含的信息
     * label:显示二维码的QLabel控件
     * logo:二维码中间显示的图片
     * scale:中间图片的缩放比例
     * */
    void Widget::GenerateQRcode(QString tempstr, QLabel *label, const QString &logo, float scale)
    {
        GenerateQRcode(tempstr,  label);
        int width = label->width();
        int height = label->height();
        int logo_width = width *scale;
        int logo_height =  height * scale;
        int logo_x = (width - logo_width) / 2;
        int logo_y = (width - logo_height) / 2;
     
        const QPixmap *pix = label->pixmap();
        QPixmap temppix(logo);
        QPixmap pix1 = temppix.scaled(QSize(logo_width, logo_height), Qt::KeepAspectRatio);
        QPixmap pix2(width, height);
     
        QPainter *painter = new QPainter(&pix2);
        QColor background(Qt::white);
        painter->setBrush(background);
        painter->setPen(Qt::NoPen);
        painter->drawRect(0, 0, width, height);
        QColor foreground(Qt::black);
        painter->setBrush(foreground);
     
        painter->drawPixmap(0,0, width, height, *pix);
        painter->drawPixmap(logo_x,logo_y, logo_width, logo_height, pix1);
        label->setPixmap(pix2);
        delete painter;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71

    这里以如下程序为例

        QLabel *lab1 = new QLabel(this);
        lab1->setGeometry(10,100,200,200);
        QLabel *lab2 = new QLabel(this);
        lab2->setGeometry(300,100,200,200);
        GenerateQRcode("123456789", lab1, ":Imag/jiasu.png",0.2);
        GenerateQRcode("123456789", lab2);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在这里插入图片描述

  • 相关阅读:
    DataBinding 基础用法
    氮化镓(GaN)功率半导体之预测
    快速理解python中的可迭代对象、迭代器、生成器
    【数据结构】链表C语言编写的,它定义了一个链表,并实现了一些基本的链表操作,如创建新节点、插入节点、清空链表、输出链表以及查找节点
    vue css变量实现多主题皮肤切换
    【slam十四讲第二版】【课后习题】【第九讲~后端2】
    LVS 集群架构介绍 (linux 虚拟服务器)
    TensorFlow 2.9的零零碎碎(四)-模型的输入
    TCP 连接的状态详解以及故障排查
    ios环境搭建
  • 原文地址:https://blog.csdn.net/m0_46577050/article/details/133975030