目錄
一、前言
本文主要介紹二維碼生成和解析的相關知識和例程
二、相關知識
①二維碼生成:
主要用到的是開源的二維碼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