目录
一、前言
二、相关知识
三、效果展示
四、主要源码简析
五、源码Demo
一、前言
本文主要介绍二维码生成和解析的相关知识和例程
二、相关知识
①二维码生成:
主要用到的是开源的二维码QR码编码库qrencode,需要使用到的库文件为下面的:
库里最重要的是下面的二维码生成函数:
/*
string是生成二维码的字符串;
2表示二维码的版本,一般选1或2都可以;
QR_ECLEVEL_L表示容错级别,容错级别越高,相同的字符串生成的二维码就越复杂,相对应的识别二维码摄像头也就需求精度越高;
QR_MODE_8表示生成二维码数据的类型,一般选QR_MODE_8;
最后一个涉及到库生成二维码的一些判断,选0即可。
返回值是生成二维码的全部信息
*/
qr = QRcode_encodeString(string,2,QR_ECLEVEL_L,QR_MODE_8,0);
根据上面的函数可获得生成二维码的信息,还需将二维码的结构体信息,转换成图片,用QPainter处理即可。qr->data包含了二维码图像的信息,其中每个数据的bit0位代表了点的颜色,1表示黑色,0表示白色。画图时先将画布背景色设置为白色,然后将为1的点画成黑色,为0的点不画。
②二维码/条形码解析
主要用到的是QZXing,网上有很多现成的,我的Demo也提供,主要的二维码/条形码解析过程:
QZXing decoder;
//解析类型:CODE128条形码和二维码,可自选
decoder.setDecoder( QZXing::DecoderFormat_CODE_128 | QZXing::DecoderFormat_QR_CODE);
QString result = decoder.decodeImage(img);
三、效果展示
①二维码生成
②二维码/条形码解析
四、主要源码简析
①二维码生成
qrcodegenerate.h
#ifndef QRCODEGENERATE_H
#define QRCODEGENERATE_H
#include <QWidget>
#include "./qrencode/qrencode.h"
#include <QPainter>
namespace Ui {
class QrcodeGenerate;
}
class QrcodeGenerate : public QWidget
{
Q_OBJECT
public:
explicit QrcodeGenerate(QWidget *parent = 0);
~QrcodeGenerate();
void generateString(const QString &str);
bool saveImage(const QString &fileName, int size=250);
protected:
void paintEvent(QPaintEvent *);
QSize sizeHint() const;
QSize minimumSizeHint() const;
private:
Ui::QrcodeGenerate *ui;
void draw(QPainter &painter, int width, int height);
QRcode *qr;
};
#endif // QRCODEGENERATE_H
qrcodegenerate.cpp
#include "qrcodegenerate.h"
#include "ui_qrcodegenerate.h"
QrcodeGenerate::QrcodeGenerate(QWidget *parent) :
QWidget(parent),
ui(new Ui::QrcodeGenerate)
{
ui->setupUi(this);
qr = NULL;
}
QrcodeGenerate::~QrcodeGenerate()
{
if(qr != NULL)
{
QRcode_free(qr);
qr = NULL;
}
delete ui;
}
bool QrcodeGenerate::saveImage(const QString& fileName, int size)
{
if(size != 0 && !fileName.isEmpty())
{
QImage image(size, size, QImage::Format_Mono);
QPainter painter(&image);
QColor background(Qt::white);
painter.setBrush(background);
painter.setPen(Qt::NoPen);
painter.drawRect(0, 0, size, size);
if(qr != NULL)
{
draw(painter, size, size);
}
return image.save(fileName);
}
else
{
return false;
}
}
void QrcodeGenerate::generateString(const QString& str)
{
if(qr != NULL)
{
QRcode_free(qr);
}
//2:生成二维码版本,建议选1或2;QR_ECLEVEL_L:容错级别;QR_MODE_8:生成data数据的类型
qr = QRcode_encodeString(str.toStdString().c_str(),
2,
QR_ECLEVEL_L,
QR_MODE_8,
0);
update();
}
void QrcodeGenerate::draw(QPainter &painter, int width, int height)
{
QColor foreground(Qt::black);
painter.setBrush(foreground);
const int qr_width = qr->width > 0 ? qr->width : 1;
double scale_x = width / qr_width;
double scale_y = height / qr_width;
for( int y = 0; y < qr_width; y ++)
{
for(int x = 0; x < qr_width; x++)
{
unsigned char b = qr->data[y * qr_width + x];
//bit0位代表了点的颜色,1表示黑色,0表示白色,我们只要在白背景下画黑点
if(b & 0x01)
{
QRectF r(x * scale_x, y * scale_y, scale_x, scale_y);
painter.drawRects(&r, 1);
}
}
}
}
//ui重绘事假
void QrcodeGenerate::paintEvent(QPaintEvent *)
{
QPainter painter(this);
//把背景设为纯白
QColor background(Qt::white);
painter.setBrush(background);
painter.setPen(Qt::NoPen);
painter.drawRect(0, 0, width(), height());
if(qr != NULL)
{
draw(painter, width(), height());
}
}
QSize QrcodeGenerate::sizeHint() const
{
QSize s;
if(qr != NULL)
{
int qr_width = qr->width > 0 ? qr->width : 1;
s = QSize(qr_width * 4, qr_width * 4);
}
else
{
s = QSize(50, 50);
}
return s;
}
QSize QrcodeGenerate::minimumSizeHint() const
{
QSize s;
if(qr != NULL)
{
int qr_width = qr->width > 0 ? qr->width : 1;
s = QSize(qr_width, qr_width);
}
else
{
s = QSize(50, 50);
}
return s;
}
②二维码/条形码解析
void MainWindow::on_pushButton_clicked()
{
ui->lineEdit->clear();
QString filename = QFileDialog::getOpenFileName(this,"file","./","any files(*.*)"";;any files(*.png)");
QImage img; //加载图像
if(!(img.load(filename)))
{
QMessageBox::information(this,"Warning", "Open Picture fail!");
return;
}
img = img.scaled(ui->label->width(),ui->label->height(),Qt::KeepAspectRatio);
ui->label->setPixmap(QPixmap::fromImage(img));
QZXing decoder;
//解析CODE128一维码和二维码
decoder.setDecoder( QZXing::DecoderFormat_CODE_128 | QZXing::DecoderFormat_QR_CODE);
QString result = decoder.decodeImage(img);
if(result.isEmpty())
{
QMessageBox::about(this,"warning","Wrong picture format!");
return;
}
ui->lineEdit->setText(result);
}
五、源码Demo
①二维码生成
链接:https://pan.baidu.com/s/1KNcebG_K_ARRkW1tMpbq8g
提取码:844t
②二维码/条形码解析
链接:https://pan.baidu.com/s/1Cr-eBjd3XeADcv7yclvI7g
提取码:fr4p