C++中生成二维码-libqrencode

本文介绍了如何在C++中使用libqrencode库生成二维码,特别是在QT环境中将文本转换为二维码并显示在界面上。文章提到了libqrencode的基本用法,包括在Linux和Windows上的安装,以及在QT中直接绘制二维码的实现。还提供了一个简单的代码示例来演示编码过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

二维码的种类很多。本文仅介绍,如何用C++生成QR码(QRcode)。通常而言,我们不需要知道QR码的详细结构,如QrCode的结构原理与实战 | 张展鹏的博客。我们只需要,可以将文本转换成二维码,控制二维码的大小(分辨率),即可。所以,我推荐在这个站点里面逛逛:什么是QR码? | QRcode.com | DENSO WAVE

建议读下上面链接中的这几个内容:

本文目前,仅简单使用GitHub - fukuchi/libqrencode: A fast and compact QR Code encoding library,生成二维码。

本文详细代码见仓库


libqrencode

本节目标:将一个字符串转换成一个png图片。

没有啥好的参考示例,所以我们从命令行入手。首先,在Linux下,安装qrencode的二进制文件和库。然后,通过命令将文本转换成图片。我们顺着命令的执行逻辑,看下命令的源码,即可了解大体操作。

# linux安装二进制和库
sudo apt install qrencode libqrencode

# 将文本转换成图片
qrencode --output=tmp.png --type=PNG "hello world"


# window中安装库(库中没有包含二进制,默认的编写选项没开吧)
vcpkg.exe install libqrencode

结合QRencode: Main Page,阅读qrencode(intext, length, outfile)处的代码,可以看到逻辑分为两步:将字符串转换成可以绘制QR二维的信息结构;将信息结构转换成图片。将信息结构转换成图片部分,本文不介绍(我也没去看png的api,我直接把qrencode生成png的代码抠出来运行的)。

下面我们来写demo,演示下。这里仅仅列出核心逻辑。转换成图片的writePNG函数代码没有列出,详细见仓库。

int main(int argc, char *argv[]) {
  std::string str("你好,世界");
  int version = 0;
  QRcode *qrcode =
      QRcode_encodeString(str.c_str(), version, QR_ECLEVEL_L, QR_MODE_8, 1);
  // QRcode *qrcode = QRcode_encodeData(
  //     str.size(), (const unsigned char *)str.c_str(), version, QR_ECLEVEL_L);

  if (qrcode == NULL) {
    if (errno == ERANGE) {
      fprintf(stderr,
              "Failed to encode the input data: Input data too large\n");
    } else {
      perror("Failed to encode the input data");
    }
    return -1;
  }

  if (qrcode->version != version) {
    std::cout << "the input data too large" << std::endl;
    std::cout << "change version from " << version << " to " << qrcode->version;
  }

  writePNG(qrcode, "tmp.png", PNG_TYPE);
  QRcode_free(qrcode);
  return 0;
}

下面简单介绍上上面的过程。

  • extern QRcode *QRcode_encodeString(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive); 将传入的字符串(不能包含null)转换成QRcode的信息。version是版本号,不同版本可以容纳不同的字符数量(详细见前言中的链接)。可以根据传入的字符数量,版本号,选择合适的纠错等级。如果要传入非字母数字的内容,使用QR_MODE_8,对字符串进行编码(不知道它咋编码的,可能是utf8吧)。

  • QRcode_encodeString编码失败,返回NULL, 错误记录在erron中。

  • 如果不严格限制版本。当传入的字符数量大于版本所能容纳的字符数量时,版本会自动调整。如果不是很在意版本,传入0即可,会根据传入的文本选择最小的版本。

在windows上编译代码需要注意下。如果没有添加-DCMAKE_BUILD_TYPE=Releasepkgconfig默认链接的是debug版本,见:release project using pkgconfig link with debug library · Issue #29762 · microsoft/vcpkg · GitHub

cmake .. -DCMAKE_BUILD_TYPE=Release
cmake --build . --config Release

结果如下。

在这里插入图片描述


在qt中调用libqrencode

本节目标:点击按钮,将文本框中的字符串,转换成二维码在界面上显示。

不需要在生成图片了,而是直接在qt中绘制。QRcode Struct中的数据,最低位为1/0为黑色/白色。

参考:Qt + libqrencode 生成二维码_qt生成二维码_龚建波的博客-CSDN博客Qt生成二维码

没啥难度,照葫芦画瓢,抄抄改改就好。

QPixmap MainWindow::GernerateQRCode(const QString &text, int scale) {
  QPixmap ret;
  int version = 0;
  QRcode *qrcode = QRcode_encodeString(text.toStdString().c_str(), version,
                                       QR_ECLEVEL_L, QR_MODE_8, 1);
  if (qrcode == NULL) {
    qDebug() << "Failed to encode the input data, errno is: " << errno;
    return ret;
  }
  auto cleanup = qScopeGuard([qrcode] { QRcode_free(qrcode); });

  if (qrcode->version != version) {
    qDebug() << "the input data too large";
    qDebug() << "change version from " << version << " to " << qrcode->version;
  }

  int width = qrcode->width * scale;
  int heigh = qrcode->width * scale;
  QImage image(width, heigh, QImage::Format_Mono);
  QPainter painter(&image);
  painter.fillRect(0, 0, width, heigh, Qt::white); // 背景填充白色
  painter.setPen(Qt::NoPen); // 填充但是不需要边界线
  painter.setBrush(QBrush(Qt::black, Qt::SolidPattern)); // 设置画笔为黑色
  for (int y = 0; y < qrcode->width; ++y) {
    for (int x = 0; x < qrcode->width; ++x) {
      if (qrcode->data[y * qrcode->width + x] & 0x01) {
        painter.drawRect(x * scale, y * scale, scale, scale);
      }
    }
  }
  ret = QPixmap::fromImage(image);
  return ret;
}

void MainWindow::onButtonClicked() {
  ui->button_qrcode->setEnabled(false);

  int width = ui->lab_qrcode->width();
  int heigh = ui->lab_qrcode->height();
  QString text = ui->textEdit_qrcode->toPlainText();
  if (!text.isEmpty()) {
    QPixmap pixmap = GernerateQRCode(text, 10);
    pixmap = pixmap.scaled(width, heigh, Qt::IgnoreAspectRatio,
                           Qt::SmoothTransformation);
    ui->lab_qrcode->setPixmap(pixmap);
  }

  ui->button_qrcode->setEnabled(true);
}

结果如下。

在这里插入图片描述


其他

还有些其他库没有尝试:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

da1234cao

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

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

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

打赏作者

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

抵扣说明:

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

余额充值