Qt项目实战3:二维码生成器
阅读原文时间:2021年04月23日阅读:11

qrtool项目简介

二维码(Qrcode)现在越来越常用,扫码支付、扫码添加好友、扫码乘坐公交车和地铁,我们的生活已经与二维码息息相关。这里我们使用qt软件+qrencode开源库来生成、显示、保存二维码图片,并且支持简单的二维码容错率修改和大小修改。
ui效果图如下:

qrencode开源库

libqrencode 是生成二维码数据的开源库。 github链接
在Windows平台,使用CMake工具构建libqrencode工程,生成静态库,在qt工程中使用。

构建qrencode工程

安装cmake工具 官网下载链接
使用cmake构建工程

修改工程配置信息:

这里需要注意的是,构建qrencode库,不关联iconv和libpng库。
使用Configure命令生成工程配置文件,使用Generate命令生成Makefile文件,构建完成。

编译libqrencode库

构建完成后,进入命令行,进行编译:

Microsoft Windows [版本 10.0.17134.228]
(c) 2018 Microsoft Corporation。保留所有权利。

C:\Users\Administrator> cd /d E:\opensource\libqrencode-master\build

E:\opensource\libqrencode-master\build>mingw32-make
-- Could NOT find ZLIB (missing: ZLIB_LIBRARY ZLIB_INCLUDE_DIR)
-- Could NOT find PNG (missing: PNG_LIBRARY PNG_PNG_INCLUDE_DIR)
-- Could NOT find ICONV (missing: ICONV_FOUND_ANY ICONV_INCLUDE_DIR)
-- ------------------------------------------------------------
-- [QRencode] Configuration summary.
-- ------------------------------------------------------------
--  System configuration:
--  .. Processor type .............. = AMD64
--  .. CMake executable ............ = D:/Program Files/CMake/bin/cmake.exe
--  .. CMake version ............... = 3.12.1
--  .. System name ................. = Windows-10.0.17134
--  .. C++ compiler ................ =
--  .. C compiler .................. = D:/software/Qt/Qt5.6.0/Tools/mingw492_32/bin/gcc.exe
--  .. size(void*) ................. = 4
--  Dependencies:
--  .. Thread library of the system  =
--  .. Iconv ....................... = FALSE
--  .... Iconv includes ............ = ICONV_INCLUDE_DIR-NOTFOUND
--  .... Iconv library ............. = ICONV_LIBRARY-NOTFOUND
--  .. ZLIB ........................ = FALSE
--  .. PNG ......................... = FALSE
--  .... PNG includes .............. =
--  .... PNG library ............... =
--  Project configuration:
--  .. Build test programs  ........ = OFF
--  .. Build utility tools  ........ = OFF
--  .. Disable PNG support  ........ = OFF
--  .. Installation prefix ......... = E:/opensource/libqrencode-master/install
-- ------------------------------------------------------------
-- Configuring done
-- Generating done
-- Build files have been written to: E:/opensource/libqrencode-master/build
Scanning dependencies of target qrencode
[ 10%] Building C object CMakeFiles/qrencode.dir/qrencode.c.obj
[ 20%] Building C object CMakeFiles/qrencode.dir/qrinput.c.obj
[ 30%] Building C object CMakeFiles/qrencode.dir/bitstream.c.obj
[ 40%] Building C object CMakeFiles/qrencode.dir/qrspec.c.obj
[ 50%] Building C object CMakeFiles/qrencode.dir/rsecc.c.obj
[ 60%] Building C object CMakeFiles/qrencode.dir/split.c.obj
[ 70%] Building C object CMakeFiles/qrencode.dir/mask.c.obj
[ 80%] Building C object CMakeFiles/qrencode.dir/mqrspec.c.obj
[ 90%] Building C object CMakeFiles/qrencode.dir/mmask.c.obj
[100%] Linking C static library libqrencode.a
[100%] Built target qrencode

E:\opensource\libqrencode-master\build>mingw32-make install
[100%] Built target qrencode
Install the project...
-- Install configuration: ""
-- Up-to-date: E:/opensource/libqrencode-master/install/share/man/man1/qrencode.1
-- Up-to-date: E:/opensource/libqrencode-master/install/lib/pkgconfig/libqrencode.pc
-- Up-to-date: E:/opensource/libqrencode-master/install/include/qrencode.h
-- Installing: E:/opensource/libqrencode-master/install/lib/libqrencode.a

E:\opensource\libqrencode-master\build>

使用mingw32-makemingw32-make install命令编译和安装库文件。安装完成后,将生成的libqrencode库拷贝到qt工程中以供使用。

生成二维码数据

使用QRcode_encodeString函数来生成二维码数据,函数原型如下:

QRcode *QRcode_encodeString(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive);

参数string表示需要转换的数据,QRecLevel和QRencodeMode枚举类型如下所示。casesensitive表示是否使能大小写敏感,默认启用就可以了。

/**
 * Level of error correction.
 */
typedef enum {
    QR_ECLEVEL_L = 0, ///< lowest
    QR_ECLEVEL_M,
    QR_ECLEVEL_Q,
    QR_ECLEVEL_H      ///< highest
} QRecLevel;

/**
 * Encoding mode.
 */
typedef enum {
    QR_MODE_NUL = -1,   ///< Terminator (NUL character). Internal use only
    QR_MODE_NUM = 0,    ///< Numeric mode
    QR_MODE_AN,         ///< Alphabet-numeric mode
    QR_MODE_8,          ///< 8-bit data mode
    QR_MODE_KANJI,      ///< Kanji (shift-jis) mode
    QR_MODE_STRUCTURE,  ///< Internal use only
    QR_MODE_ECI,        ///< ECI mode
    QR_MODE_FNC1FIRST,  ///< FNC1, first position
    QR_MODE_FNC1SECOND, ///< FNC1, second position
} QRencodeMode;

encode成功后,返回QRcode结构体数据:

/**
 * QRcode class.
 * Symbol data is represented as an array contains width*width uchars.
 * Each uchar represents a module (dot). If the less significant bit of
 * the uchar is 1, the corresponding module is black. The other bits are
 * meaningless for usual applications, but here its specification is described.
 *
 * @verbatim
   MSB 76543210 LSB
       |||||||`- 1=black/0=white
       ||||||`-- 1=ecc/0=data code area
       |||||`--- format information
       ||||`---- version information
       |||`----- timing pattern
       ||`------ alignment pattern
       |`------- finder pattern and separator
       `-------- non-data modules (format, timing, etc.)
   @endverbatim
 */
typedef struct {
    int version;         ///< version of the symbol
    int width;           ///< width of the symbol
    unsigned char *data; ///< symbol data
} QRcode;

使用encode转换的data和width数据,即可绘制出二维码图片。

绘制二维码图片

在Qt中,使用QImage类来创建一个图片实例,使用QPainter类来绘制图片。
绘制图片步骤:

  • 创建QPainter实例,在已经存在的image实例上绘制

  • 创建一张空白的画布

  • 使用黑色画刷,根据数据宽度画像素矩形

  • 将二维码生成的数据填充在画布上

    void Widget::genQrcodeImage(char *qr_str, int width, int height)
    {
    QRcode *qrcode = NULL;

    if (qr_str == NULL || width <= 0 || height <= 0)
        return ;
    
    qrcode = QRcode_encodeString(qr_str, qrcode_version, QR_ECLEVEL_M, QR_MODE_8, 1);
    if(qrcode != NULL) {
        QPainter painter(image);
        unsigned char *point = qrcode->data;
        painter.setPen(Qt::NoPen);
        painter.setBrush(Qt::white);
        painter.drawRect(0, 0, width, height);
        double scale = (width - 2.0 * margin) / qrcode->width;
        painter.setBrush(Qt::black);
        for (int y = 0; y < qrcode->width; y++) {
            for (int x = 0; x < qrcode->width; x++) {
                if (*point & 1) {
                    QRectF r(margin + x * scale, margin + y * scale, scale, scale);
                    painter.drawRects(&r, 1);
                }
                point++;
            }
        }
        point = NULL;
        QRcode_free(qrcode);
        qrcode = NULL;
    }

    }

绘制完成后,在QLabel上显示图片:

QPixmap pixmap = QPixmap::fromImage(*image);
ui->qrLabel->setPixmap(pixmap);

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章