目录

一、前言

二、相关知识

三、效果展示

四、主要源码简析

五、源码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

Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐