--- layout: post title: "QRenCode 库的编译和使用" subtitle: "" description: "在项目中使用二维码通常会用到 qrencode 库。本文简单介绍 qrencode 库的编译安装并结合 Qt 进行实例演示。" excerpt: "本文对 qrencode 库的编译和基本使用进行了介绍。" date: 2020-05-20 14:22:00 author: "Rick Chan" tags: ["Development", "Library","QRenCode"] categories: ["Software"] published: true --- 在项目中使用二维码通常会用到 qrencode 库。本文简单介绍 qrencode 库的编译安装并结合 Qt 进行实例演示。 ## 编译 qrencode 库 在 Manjaro 上直接 ```bash sudo pacman -S qrencode ``` 安装即可。不能自动安装的也可以通过源码进行编译,config 之后 make 就能搞定。另外源码中有 cmake 文件,因此也可以使用 Qt cmake 进行编译。 ## 一点点说明 一开始以为 qrencode 会直接输出二维码图像,但实际上不是这样的,导致走了许多弯路。qrencode 的输出主要是 QRcode 对象。QRcode 用来表示二维码数据和信息,QRcode 的 data 字段中每个字节的最低位表示二维码对应位置是白色方块还是黑色方块(1-7位包含了其他信息)。所以拿到 QRcode 对象后要经过转换才能得到最终的二维码图片。 ## 参考代码 Pro 文件如下: ```qt # Q2RCode.pro QT += gui CONFIG += c++11 console CONFIG -= app_bundle # The following define makes your compiler emit warnings if you use # any Qt feature that has been marked deprecated (the exact warnings # depend on your compiler). Please consult the documentation of the # deprecated API in order to know how to port your code away from it. DEFINES += QT_DEPRECATED_WARNINGS # You can also make your code fail to compile if it uses deprecated APIs. # In order to do so, uncomment the following line. # You can also select to disable deprecated APIs only up to a certain version of Qt. #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 SOURCES += \ main.cpp # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target unix:!macx: LIBS += -lqrencode ``` main.cpp 如下: ```cpp /** * @file main.cpp * @author Rich Chan (cy187lion@sina.com) * @brief qrencode 库使用示例. * @version 0.1 * @date 2020-05-15 * * @copyright Copyright (c) 2020 * */ #include #include #include #include /** * @brief Draw 通过 QRcode 生成图像. * @param qrc 输入的二维码数据. * @param image 生成的图像. */ void Draw(QRcode *qrc, QImage &image) { const int width = qrc->width > 0 ? qrc->width : 1; double scale = image.width()/width; QPainter painter; painter.begin(&image); // 白色背景图. QColor background(Qt::white); painter.setBrush(background); painter.setPen(Qt::NoPen); painter.drawRect(0, 0, image.width(), image.width()); // 码值为黑色. QColor foreground(Qt::black); painter.setBrush(foreground); // 二维码数据转换为图像需要进行放大, 否则将由单个像素点表示码值, 看起来很怪异. for(int y=0; ydata[y*width+x]; /** * qrc->data 的每个字节对应二维码中的一个小方块, 如果该字节最低位为高则绘制黑色方块. * 字节中具体每一位的含义如下 * * bit0: 1=black/0=white * bit1: data and ecc code area * bit2: format information * bit3: version information * bit4: timing pattern * bit5: alignment pattern * bit6: finder pattern and separator * bit7: non-data modules (format, timing, etc.) */ if(b&0x01) { QRectF r(x*scale, y*scale, scale, scale); painter.drawRects(&r, 1); } } } painter.end(); } int main(void) { // 将字符串转换为二维码数据, QRcode_encodeString 的参数请参照官方文档. QRcode *qrc = QRcode_encodeString("Hello, This is a test!", 0, QR_ECLEVEL_H, QR_MODE_8, 1); QImage image(256, 256, QImage::Format_RGB32); Draw(qrc, image); // 使用 QImage 将二维码保存为图片, 字符串扩展名决定了图像编码格式. image.save("./qrcode.png"); } ```