一、简介
条形码:
条形码(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