二维码(Qrcode)现在越来越常用,扫码支付、扫码添加好友、扫码乘坐公交车和地铁,我们的生活已经与二维码息息相关。这里我们使用qt软件+qrencode开源库来生成、显示、保存二维码图片,并且支持简单的二维码容错率修改和大小修改。
ui效果图如下:
libqrencode
是生成二维码数据的开源库。 github链接 。
在Windows平台,使用CMake工具构建libqrencode工程,生成静态库,在qt工程中使用。
安装cmake工具 官网下载链接。
使用cmake构建工程
修改工程配置信息:
这里需要注意的是,构建qrencode库,不关联iconv和libpng库。
使用Configure命令生成工程配置文件,使用Generate命令生成Makefile文件,构建完成。
构建完成后,进入命令行,进行编译:
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-make
和mingw32-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类来绘制图片。
绘制图片步骤:
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);