qt之条形码与二维码的生成

一、简介

条形码:
    条形码(barcode)是将宽度不等的多个黑条和空白,按照一定的编码规则排列,用以表达一组信息的图形标识符。常见的条形码是由反射率相差很大的黑条(简称条)和白条(简称空)排成的平行线图案。本工程使用的是GNUBarCode库。

二维码:
    二维码又称二维条码,常见的二维码为QR Code,QR全称Quick Response,是一种编码方式。它比传统的Bar Code条形码能存更多的信息,也能表示更多的数据类型。本工程使用的是Libqrencode源码。

二、界面展示

请添加图片描述

二、核心代码

2.1 条形码 (ctbarcode.h、ctbarcode.cpp)

ctbarcode.h

#ifndef CTBARCODE_H
#define CTBARCODE_H

#include <QObject>
#include <QImage>
#include <QPainter>
#include "barcode.h"


#define  BAR_SAFE_FREE(p) \
do { \
    if(p) \
    { \
        free(p); \
        p = nullptr; \
    } \
} while(0)

class ctBarCode : public QObject
{
    Q_OBJECT
public:
    ctBarCode(QObject *parent = nullptr);
    ~ctBarCode();

    static ctBarCode& getInstance();

    //开始编码
    bool StartEncode(const QString& sTxt);
    //设置条码的类型
    void setBarcodeType(int nType);
    //设置条码四周留白区域的大小
    void setMargin(int nMargin);
    //设置是否在条码上/下面显示对应文字
    void setTxtShow(bool bTxtShow);

    //返回条码的尺寸
    QSize size();
    QSize minSize();

    //前景色
    QColor getFGColor() const;
    void setFGColor(const QColor& fgColor);

    //背景色
    QColor getBGColor() const;
    void setBGColor(const QColor& bgColor);

    //渲染绘制
    QImage paintImage(double dWidthScale = 2, int nHeight = 60, QImage::Format format = QImage::Format_RGB32);
    QImage paintImage(QSize size, QImage::Format format = QImage::Format_RGB32);
    bool render(QPainter &painter);
    bool render(QPainter &painter, QRect rect);

private:
    bool updateSizeInfo();
    bool drawBarCode(QPainter &painter);
    bool drawBarText(QPainter &painter);


private:
    Barcode_Item* m_pBcItem = nullptr;
    int m_nBcType = BARCODE_128;
    bool m_bTxtShow = false;
    QString m_sText;
    QColor m_fgColor = Qt::black;
    QColor m_bgColor = Qt::white;
    int m_nMargin = 5;
    int m_nMinWidth;
    int m_nMinHeight;
    int m_nGlobalWidth;
    int m_nGlobalHeight;

};

#endif // CTBARCODE_H

ctbarcode.cpp

#include "ctbarcode.h"
#include <math.h>


ctBarCode::ctBarCode(QObject *parent) : QObject (parent)
{
}

ctBarCode::~ctBarCode()
{
    if(m_pBcItem)
    {
        BAR_SAFE_FREE(m_pBcItem->ascii);
        BAR_SAFE_FREE(m_pBcItem->partial);
        BAR_SAFE_FREE(m_pBcItem->textinfo);
        BAR_SAFE_FREE(m_pBcItem->encoding);

        free(m_pBcItem);
    }
}

ctBarCode &ctBarCode::getInstance()
{
    static ctBarCode s_obj;
    return s_obj;
}

bool ctBarCode::StartEncode(const QString &sTxt)
{
    if(m_pBcItem)
    {
        BAR_SAFE_FREE(m_pBcItem->ascii);
        BAR_SAFE_FREE(m_pBcItem->partial);
        BAR_SAFE_FREE(m_pBcItem->textinfo);
        BAR_SAFE_FREE(m_pBcItem->encoding);

        free(m_pBcItem);
    }

    m_pBcItem = Barcode_Create(static_cast<char*>(sTxt.toLocal8Bit().data()));
    if(m_pBcItem)
    {
        m_pBcItem->margin = m_nMargin;

        int nFlags;
        if(m_bTxtShow)
        {
            nFlags = m_nBcType;
        }
        else
        {
            nFlags = m_nBcType | BARCODE_NO_ASCII;
        }
        m_pBcItem->flags = nFlags;

        Barcode_Encode(m_pBcItem, nFlags);

        updateSizeInfo();

    }
    else
        return false;

    return true;
}

void ctBarCode::setBarcodeType(int nType)
{
    m_nBcType = nType;
}

void ctBarCode::setMargin(int nMargin)
{
    m_nMargin = nMargin;
}

void ctBarCode::setTxtShow(bool bTxtShow)
{
    m_bTxtShow = bTxtShow;
}

QSize ctBarCode::size()
{
    return QSize(m_nGlobalWidth, m_nGlobalHeight);
}

QSize ctBarCode::minSize()
{
    if(m_pBcItem)
        return QSize(m_pBcItem->width, m_pBcItem->height);

    return QSize();
}

QColor ctBarCode::getFGColor() const
{
    return m_fgColor;
}

void ctBarCode::setFGColor(const QColor &fgColor)
{
    m_fgColor = fgColor;
}

QColor ctBarCode::getBGColor() const
{
    return m_bgColor;
}

void ctBarCode::setBGColor(const QColor &bgColor)
{
    m_bgColor = bgColor;
}

QImage ctBarCode::paintImage(double dWidthScale, int nHeight, QImage::Format format)
{
    if(!m_pBcItem)
        return QImage();

    int bcWidth = m_pBcItem->width; // 保存现场
    int bcHeight = m_pBcItem->height;
    float bcScalef = static_cast<float>(m_pBcItem->scalef);

    m_pBcItem->width = static_cast<int>(m_pBcItem->width * dWidthScale);
    m_pBcItem->scalef = dWidthScale;
    m_pBcItem->height = nHeight;

    int w = m_pBcItem->width + 2 * m_pBcItem->margin;
    int h = m_pBcItem->height + 2 * m_pBcItem->margin;

    QImage img(w, h, format);
    QPainter painter(&img);
    img.fill(m_bgColor);
    painter.setBrush(m_fgColor);
    render(painter);

    m_pBcItem->width = bcWidth; // 恢复原状
    m_pBcItem->height = bcHeight;
    m_pBcItem->scalef = static_cast<double>(bcScalef);
    return img;
}

QImage ctBarCode::paintImage(QSize size, QImage::Format format)
{
    if(!m_pBcItem)
        return QImage();

    int nWidth = size.width();
    int nHeight = size.height();
    return paintImage(nWidth / m_pBcItem->width, nHeight, format);
}

bool ctBarCode::render(QPainter &painter)
{
    if(!m_pBcItem)
        return false;

    int w = m_pBcItem->width + 2 * m_pBcItem->margin;
    int h = m_pBcItem->height + 2 * m_pBcItem->margin;
    painter.fillRect(QRect(0, 0, w, h), m_bgColor);

    if (!m_pBcItem->partial || !m_pBcItem->textinfo)
    {
        m_pBcItem->error = EINVAL;
        return false;
    }
    drawBarCode(painter);

    if(!(m_pBcItem->flags & BARCODE_NO_ASCII) )
    {
        drawBarText(painter);
    }
    return true;
}

bool ctBarCode::render(QPainter &painter, QRect rect)
{
    int xoffset = m_pBcItem->xoff;
    int yoffset = m_pBcItem->yoff;
    int width = m_pBcItem->width;
    int height = m_pBcItem->height;
    double scalef = m_pBcItem->scalef;

    m_pBcItem->xoff = rect.left();
    m_pBcItem->xoff = rect.top();
    m_pBcItem->width = rect.width() - 2 * m_nMargin;
    m_pBcItem->height = rect.height() - 2 * m_nMargin;
    m_pBcItem->scalef = 0.0;

    updateSizeInfo();
    bool ret = render(painter);

    m_pBcItem->xoff = xoffset;
    m_pBcItem->yoff = yoffset;
    m_pBcItem->width = width;
    m_pBcItem->height = height;
    m_pBcItem->scalef = scalef;

    return ret;
}

bool ctBarCode::updateSizeInfo()
{
    if(!m_pBcItem)
        return false;

    if (!m_pBcItem->partial || !m_pBcItem->textinfo )
    {
        m_pBcItem->error = EINVAL;
        return false;
    }

    //1.计算nBarLen
    int nBarLen = m_pBcItem->partial[0] - '0';
    for (char * ptr = m_pBcItem->partial + 1; *ptr; ptr++)
    {
        if (isdigit(*ptr))
        {
            nBarLen += (*ptr - '0');
        }
        else if (islower(*ptr))
        {
            nBarLen += (*ptr - 'a' + 1);
        }
    }

    m_nMinWidth = nBarLen; // 这个宽度是计算出的最小宽度
    m_nMinHeight = 80; // 默认的高度

    //The scale factor depends on bar length
    if ((fabs(m_pBcItem->scalef) < 1e-6))
    {
        if (!m_pBcItem->width)
        {
            m_pBcItem->width = nBarLen;
        }
        m_pBcItem->scalef = static_cast<double>(m_pBcItem->width) / static_cast<double>(nBarLen);
    }

    //The width defaults to "just enough"
    if (!m_pBcItem->width)
    {
        m_pBcItem->width = static_cast<int>(nBarLen * m_pBcItem->scalef) + 1;
    }

    //But it can be too small, in this case enlarge and center the area
    if (m_pBcItem->width < nBarLen * m_pBcItem->scalef)
    {
        int nWidth = static_cast<int>(nBarLen * m_pBcItem->scalef + 1);
        m_pBcItem->xoff -= (nWidth - m_pBcItem->width) / 2 ;
        m_pBcItem->width = nWidth;

        //Can't extend too far on the left
        if (m_pBcItem->xoff < 0)
        {
            m_pBcItem->width += -m_pBcItem->xoff;
            m_pBcItem->xoff = 0;
        }
    }

    //The height defaults to 80 points (rescaled)
    if (!m_pBcItem->height)
    {
        m_pBcItem->height = static_cast<int>(80 * m_pBcItem->scalef);
    }

    //If too small (5 + text), reduce the scale factor and center
    int nIndex = 5 + 10 * ((m_pBcItem->flags & BARCODE_NO_ASCII) == 0);
    if (m_pBcItem->height < nIndex * m_pBcItem->scalef)
    {
        double scaleg = (static_cast<double>(m_pBcItem->height)) / nIndex;
        int wid = static_cast<int>(m_pBcItem->width * scaleg / m_pBcItem->scalef);
        m_pBcItem->xoff += ( m_pBcItem->width - wid ) / 2;
        m_pBcItem->width = wid;
        m_pBcItem->scalef = scaleg;
    }

    m_nMargin = m_pBcItem->margin;
    m_nGlobalWidth  = m_pBcItem->xoff + m_pBcItem->width  + 2 * m_pBcItem->margin;
    m_nGlobalHeight = m_pBcItem->yoff + m_pBcItem->height + 2 * m_pBcItem->margin;

    return true;
}

bool ctBarCode::drawBarCode(QPainter &painter)
{
    int nnMode = '-';
    int i, j;
    char* ptr;
    double x0, y0, yr;
    double xpos = m_pBcItem->margin + (m_pBcItem->partial[0] - '0') * m_pBcItem->scalef;
    for (ptr = m_pBcItem->partial + 1, i = 1; *ptr; ptr++, i++)
    {
        //special cases: '+' and '-'
        if (*ptr == '+' || *ptr == '-')
        {
            nnMode = *ptr;
            i++;
            continue;
        }

        if (isdigit (*ptr))
            j = *ptr - '0';
        else
            j = *ptr - 'a' + 1;

        if (i % 2)
        {
            x0 = m_pBcItem->xoff + xpos;
            y0 = m_pBcItem->yoff + m_pBcItem->margin;
            yr = m_pBcItem->height;
            if( !(m_pBcItem->flags & BARCODE_NO_ASCII))
            {
                //leave space for text
                if (nnMode == '-')
                {
                    //text below bars: 10 points or five points
                    yr -= (isdigit(*ptr) ? 10 : 5) * m_pBcItem->scalef;
                }
                else
                {
                    //text above bars: 10 or 0 from bottom, and 10 from top
                    y0 += (isdigit(*ptr) ? 10 : 0) * m_pBcItem->scalef;
                    yr -= (isdigit(*ptr) ? 20 : 10) * m_pBcItem->scalef;
                }
            }
            painter.fillRect(QRect(static_cast<int>(x0), static_cast<int>(y0),
                                   static_cast<int>((j * m_pBcItem->scalef)), static_cast<int>(yr)), m_fgColor);
        }
        xpos += j * m_pBcItem->scalef;
    }
    return true;
}

bool ctBarCode::drawBarText(QPainter &painter)
{
    int nMode = '-';
    if (!(m_pBcItem->flags & BARCODE_NO_ASCII))
    {
        painter.save();
        painter.setPen(m_fgColor);

        for (char * ptr = m_pBcItem->textinfo; ptr; ptr = strchr(ptr, ' '))
        {
            while (*ptr == ' ')
                ptr++;

            if (!*ptr)
                break;

            if (*ptr == '+' || *ptr == '-')
            {
                nMode = *ptr; continue;
            }

            double f1, f2;
            char c;
            if (sscanf(ptr, "%lf:%lf:%c", &f1, &f2, &c) != 3)
            {
                continue;
            }
            painter.setFont(QFont("Helvetica", static_cast<int>(0.8 * f2 * m_pBcItem->scalef)));
            int x_pos = static_cast<int>(m_pBcItem->xoff + f1 * m_pBcItem->scalef + m_pBcItem->margin);

            int y_pos = 0;
            if(nMode == '-')
            {
                y_pos = m_pBcItem->yoff + m_pBcItem->margin + m_pBcItem->height ;//- 8 * m_pBcItem->scalef;
            }
            else
            {
                y_pos =  m_pBcItem->yoff + m_pBcItem->margin;
            }
            painter.drawText(QPoint(x_pos, y_pos ), QString(QChar(c)));
        }
        painter.restore();
    }
    return true;
}

2.2 二维码 (ctqrcode.h、ctqrcode.cpp)

ctqrcode.h

#ifndef CTQRCODE_H
#define CTQRCODE_H

#include <QObject>
#include <QImage>
#include <QPainter>
#include "qrencode.h"


class ctQrCode : public QObject
{
    Q_OBJECT
public:
    explicit ctQrCode(QObject* parent = nullptr);
    ~ctQrCode();

    static ctQrCode& getInstance();

    void startEncode(const QString& sTxt);
    void setTextShow(bool bTxtShow);
    void setFGColor(const QColor& fgColor);
    void setBGColor(const QColor& bgColor);

    QImage paintImage(int nWidth, int nHeight, QImage::Format format = QImage::Format_RGB32);
				
private:
    QRcode* m_pQRCode = nullptr;
    QString m_sText;
    int m_nWidth = 200;
    int m_nHeight = 200;
    QColor m_fgColor = Qt::black;
    QColor m_bgColor = Qt::white;
    bool m_bTxtShow = false;
};

#endif // CTQRCODE_H

ctqrcode.cpp

#include "ctqrcode.h"

ctQrCode::ctQrCode(QObject *parent) : QObject (parent)
{

}

ctQrCode::~ctQrCode()
{

}

ctQrCode &ctQrCode::getInstance()
{
    static ctQrCode s_obj;
    return s_obj;
}

void ctQrCode::startEncode(const QString &sTxt)
{
    if(sTxt.isEmpty())
        return;

    m_sText = sTxt;
    m_pQRCode = QRcode_encodeString(m_sText.toStdString().c_str(), 2, QR_ECLEVEL_Q, QR_MODE_8, 1);
}

void ctQrCode::setTextShow(bool bTxtShow)
{
    m_bTxtShow = bTxtShow;
}

void ctQrCode::setFGColor(const QColor &fgColor)
{
    m_fgColor = fgColor;
}

void ctQrCode::setBGColor(const QColor &bgColor)
{
    m_bgColor = bgColor;
}

QImage ctQrCode::paintImage(int nWidth, int nHeight, QImage::Format format)
{
    if(m_pQRCode)
    {
        qint32 nQrcodeWidth = m_pQRCode->width > 0 ? m_pQRCode->width : 1;
        double scale_x = static_cast<double>(nWidth) / static_cast<double>(nQrcodeWidth);
        double scale_y = static_cast<double>(nHeight) / static_cast<double>(nQrcodeWidth);

        int nOffset = 14;
        QImage img = QImage(nWidth + nOffset * 2, nHeight + nOffset * 2, format);
        QPainter painter(&img);
        img.fill(m_bgColor);
        painter.setPen(Qt::NoPen);//不显示轮廓
        painter.drawRect(nOffset, nOffset, nWidth, nHeight);
        painter.setBrush(m_fgColor);

        for (qint32 y = 0; y < nQrcodeWidth; y++)
        {
            for (qint32 x = 0; x < nQrcodeWidth; x++)
            {
                unsigned char b = m_pQRCode->data[y*nQrcodeWidth + x];
                if (b & 0x01)
                {
                    QRectF r(nOffset + x * scale_x, nOffset + y * scale_y, scale_x, scale_y);
                    painter.drawRects(&r, 1);
                }
            }
        }

        if(m_bTxtShow)
        {
            painter.setPen( QColor(210, 172, 61));
            painter.drawText(nWidth/2, nHeight+nOffset*2-2, m_sText);
        }
        QPixmap mainmap = QPixmap::fromImage(img);
        return img;
    }
    return QImage();
}

2.2 主界面 (mainwindow.h、mainwindow.cpp)

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    void on_pushButton_bar_clicked();

    void on_pushButton_qr_clicked();

private:
    Ui::MainWindow *ui;

};

#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QMessageBox>
#include "ctbarcode.h"
#include "ctqrcode.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_pushButton_bar_clicked()
{
    QString sBarTxt = ui->lineEdit_bar->text();
    if(sBarTxt.isEmpty())
    {
        QMessageBox::critical(this, "myQBCode", "内容不能为空");
        return;
    }

    ctBarCode::getInstance().setBarcodeType(BARCODE_I25 | BARCODE_NO_CHECKSUM);
    if(ui->checkBox_bar->isChecked())
    {
        ctBarCode::getInstance().setTxtShow(true);
    }
    else
    {
        ctBarCode::getInstance().setTxtShow(false);
    }

    ctBarCode::getInstance().setMargin(10);
    ctBarCode::getInstance().StartEncode(sBarTxt);

    QImage barcode = ctBarCode::getInstance().paintImage(2, 80);
    ui->label_bar->setPixmap(QPixmap::fromImage(barcode));

}

void MainWindow::on_pushButton_qr_clicked()
{
    QString sQrTxt = ui->lineEdit_qr->text();
    if(sQrTxt.isEmpty())
    {
        QMessageBox::critical(this, "myQBCode", "内容不能为空");
        return;
    }

    if(ui->checkBox_qr->isChecked())
    {
        ctQrCode::getInstance().setTextShow(true);
    }
    else
    {
        ctQrCode::getInstance().setTextShow(false);
    }

    ctQrCode::getInstance().startEncode(sQrTxt);

    QImage qrcode = ctQrCode::getInstance().paintImage(200, 200);
    ui->label_qr->setPixmap(QPixmap::fromImage(qrcode));
}

三、工程链接下载

下载地址:https://download.csdn.net/download/linyibin_123/87449524

四、本文参考

https://blog.csdn.net/hhy321/article/details/120245679

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

浅笑一斤

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值