利用libdmtx 生成 DataMatrix 码

Posted liyuanbhu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了利用libdmtx 生成 DataMatrix 码相关的知识,希望对你有一定的参考价值。

利用 libdmtx 生成 DataMatrix 码

今天比较空闲,研究了 Libdmtx 生成 DM 码的方法。总体是比较简单的。
这里附上代码做个记录。

我的代码用到了 Qt 的 QPainter,没有考虑生成图片的效率问题。如果需要大批量生成 DM 码的图像,可以在 dmtxEncodeDataMatrix 调用之前设置 Libdmtx 的一些参数。这样可以做到dmtxEncodeDataMatrix 生成的数据就已经是图片的实际数据了,只要把数据copy到图像文件中就可以。

我的代码是把相关的功能封装到了一个类。

#ifndef DMCREATOR_H
#define DMCREATOR_H

/**
 * @file DMCreator.h
 * @author LiYuan
 * @email 18069211@qq.com
 * @version v1.0
 * @license GPL2.0
 * @brief libdmtx 库的一个简单封装,用于在 Qt 程序中生成 DM 条形码。
 * @details 因为用到了 QPainter 和 QImage, 所以需要 QtGui 模块。
 *          可用于 Qt4 和 Qt5 代码中。Qt6 还没有测试。
 * @copyright 2015-2022
 */

#include <QString>
#include <QPainter>
#include "dmtx.h"
class DMCreator

public:
    DMCreator();
    /**
     * @brief encodeString 将一个字符串编码为一个DataMatrix 码。采用 UTF-8 编码。
     * @param str
     * @return
     */
    bool encodeString(QString str);
    bool encodeString8Bit(QString str); // 采用 Local8Bit 编码方式。
    /**
     * @brief setColor 设置图像的前景色和背景色,通常为白底黑色码
     * @param foreground 前景色,通常为黑色
     * @param background 背景色,通常为白色
     */
    void setColor(QColor foreground = Qt::black, QColor background = Qt::white);
    /**
     * @brief renderNoBackground 用于将 DataMatrix 码画到界面上或者画到图像中。只画前景色部分,保留原始的背景。
     * @param painter
     * @param rect DataMatrix 码所在区域,可以不是正方形。但是最好是正方形。
     * @return
     */
    bool renderNoBackground(QPainter &painter, QRect rect) const;
    bool renderNoBackground(QPainter &painter, int width, int height) const;

    /**
      * @brief render 用于将 DM 码画到界面上或者画到图像中。用 background 填充背景。
      * @param painter
      * @param background 背景颜色
      * @param foreground 前景颜色
      * @param rect DM 码所在区域
      * @return
      */
     bool render(QPainter &painter,
               QColor background,
               QColor foreground,
               QRect rect = QRect()) const;


     /**
      * @brief toImage 将 DM 码转化为一个图像。
      * @param size 图像的尺寸。
      * @return
      */
     QImage toImage(QSize size = QSize(0, 0)) const;

     /**
      * @brief saveImage 将 DM 码图像保存到文件中。
      * @param fileName 文件名,需要给出后缀。
      * @param size 图像尺寸。
      * @return
      */
     bool saveImage(QString fileName, QSize size = QSize(0, 0)) const;
     /**
       * @brief size 获得 DataMatrix 码的长宽。
       * @return
       */
     QSize size() const;

private:
     bool isValid() const;
     QColor m_background;
     QColor m_foreground;
     DmtxEncode * m_enc = nullptr;
;

#endif // DMCREATOR_H

类的实现代码如下:

#include "DMCreator.h"
#include <QDebug>
DMCreator::DMCreator()
    :m_background(Qt::white),
      m_foreground(Qt::black)




void DMCreator::setColor(QColor foreground, QColor background)

    m_background = background;
    m_foreground = foreground;


bool DMCreator::encodeString8Bit(QString str)

    if(m_enc)
    
        dmtxEncodeDestroy(&m_enc);
    
    m_enc = dmtxEncodeCreate();
    assert(m_enc != NULL);
    dmtxEncodeSetProp(m_enc, DmtxPropBytesPerPixel, 1);
//    dmtxEncodeSetProp(m_enc, DmtxPropBytesPerPixel, 1);
//    dmtxEncodeSetProp(m_enc, DmtxPropBytesPerPixel, 1);

    dmtxEncodeDataMatrix(m_enc, str.length(), (unsigned char *)str.toLocal8Bit().data());

    //int bytesPerPixel = dmtxImageGetProp(m_enc->image, DmtxPropBytesPerPixel);
    return true;

bool DMCreator::encodeString(QString str)

    if(m_enc)
    
        dmtxEncodeDestroy(&m_enc);
    
    m_enc = dmtxEncodeCreate();
    assert(m_enc != NULL);
    dmtxEncodeSetProp(m_enc, DmtxPropBytesPerPixel, 1);

    qDebug() << str.size();
    qDebug() << str.length();

    QByteArray ba = str.toUtf8();
    dmtxEncodeDataMatrix(m_enc, ba.size(), (unsigned char *)ba.data());

    //int bytesPerPixel = dmtxImageGetProp(m_enc->image, DmtxPropBytesPerPixel);
    return true;


bool DMCreator::isValid() const

    if(!m_enc) return false;

    return true;

bool DMCreator::renderNoBackground(QPainter &painter, QRect rect) const

    if(!isValid()) return false;

    int width = dmtxImageGetProp(m_enc->image, DmtxPropWidth);
    int height = dmtxImageGetProp(m_enc->image, DmtxPropHeight);
    if(rect.isNull())
    
        rect.setRect(0, 0, width * 4, height * 4);
    
    const double offset_x = rect.left();
    const double offset_y = rect.top();
    const double scale_x = static_cast<double>(rect.width()) / width;
    const double scale_y = static_cast<double>(rect.height()) / height;

    int rowSizeBytes = m_enc->image->rowSizeBytes;
    int bytesPerPixel = m_enc->image->bytesPerPixel;
    for( int y = 0; y < height; y ++)
    
        for(int x = 0; x < width; x ++)
        
            unsigned char b = m_enc->image->pxl[y * rowSizeBytes  + x * bytesPerPixel];
            if(b == 0)
            
                QRectF r(offset_x + x * scale_x, offset_y + y * scale_y, scale_x, scale_y);
                painter.drawRect(r);
            
        
    
    return true;


bool DMCreator::renderNoBackground(QPainter &painter, int width, int height) const

    QRect rect(0, 0, width, height);
    return renderNoBackground(painter, rect);


bool DMCreator::saveImage(QString fileName, QSize size) const

    QImage image = toImage(size);
    return image.save(fileName);


QSize DMCreator::size()  const

    int width = dmtxImageGetProp(m_enc->image, DmtxPropWidth);
    int height = dmtxImageGetProp(m_enc->image, DmtxPropHeight);

    return QSize(width, height);


QImage DMCreator::toImage(QSize size) const

    if( !m_enc ) return QImage();
    int width = dmtxImageGetProp(m_enc->image, DmtxPropWidth);
    int height = dmtxImageGetProp(m_enc->image, DmtxPropHeight);
    if(size == QSize(0, 0))
    
        size = QSize(width * 4, height * 4);
    
    QImage image(size, QImage::Format_ARGB32);
    QPainter painter(&image);
    painter.setBrush(m_background);
    painter.setPen(Qt::NoPen);
    painter.drawRect(0, 0, size.width(), size.height());
    painter.setBrush(m_foreground);
    renderNoBackground(painter, size.width(), size.height());
    return image;


bool DMCreator::render(QPainter &painter, QColor background, QColor foreground, QRect rect) const

    if(!isValid()) return false;

    if(rect.isNull())
    
        int width = dmtxImageGetProp(m_enc->image, DmtxPropWidth);
        int height = dmtxImageGetProp(m_enc->image, DmtxPropHeight);
        rect.setRect(0, 0, width * 4, height * 4);
    
    painter.save();
    painter.setPen(Qt::NoPen);
    painter.setBrush(background);
    painter.drawRect(rect);
    painter.setBrush(foreground);
    bool ret = renderNoBackground(painter, rect);
    painter.restore();
    return ret;


这个代码还有很多不完善的地方,比如DM 码有很多参数可以设置。我这代码里都没考虑,用的全都是默认参数。后面有空了我会研究一下有哪些参数比较重要。提供一些接口。

代码使用起来很简单,下面是个简单的例子:

    DMCreator dmc;
    dmc.encodeString("12345678");
    QSize s = dmc.size() * 2;
    QImage img = dmc.toImage(s);

生成的图像如下:

下一篇讲讲如何用 Libdmtx 解码 DM 码。

以上是关于利用libdmtx 生成 DataMatrix 码的主要内容,如果未能解决你的问题,请参考以下文章

利用 libdmtx 解码 DataMatrix

利用 libdmtx 解码 DataMatrix

Data Matrix 二维码解码库 libdmtx 编译方法

Data Matrix 二维码解码库 libdmtx 编译方法

C# 生成 DataMatrix 格式的二维码

使用多线程使用 iTextSharp 生成 Datamatrix 会导致崩溃