How to draw a QR code with Qt in native C/C++
If you feel that Fukuchi's library is too large[0] for you, consider looking at Nayuki's C++ QR Code generator library[1]: https://github.com/nayuki/QR-Code-generator/tree/master/cpp
Nayuki's library requires C++11, and is portable without needing Autotools. Sample usage:
#include <string>
#include <vector>
#include "QrCode.hpp"
using namespace qrcodegen;
// Create the QR Code object
QrCode qr = QrCode::encodeText("Hello, world!", QrCode::Ecc::MEDIUM);
// Read the black & white pixels
for (int y = 0; y < qr.size; y++) {
for (int x = 0; x < qr.size; x++) {
int color = qr.getModule(x, y); // 0 for white, 1 for black
// You need to modify this part
draw_pixel_onto_QT(x, y, color);
}
}
[0]: Fukuchi: 20 files, ~7200 lines among the main .c and .h files (excluding build and test code).
[1]: Nayuki: 6 files, ~1400 lines among the main .cpp and .hpp files (excluding demo code).
EDIT 2016-12-08 by OP I decided, with permission, to add my own adaption to Qt. This code compiles and runs fine on my system, And I think it should be independent enough to work elsewhere without too many tweaks as well.
#include "QrCode.hpp"
void paintQR(QPainter &painter, const QSize sz, const QString &data, QColor fg)
{
// NOTE: At this point you will use the API to get the encoding and format you want, instead of my hardcoded stuff:
qrcodegen::QrCode qr = qrcodegen::QrCode::encodeText(data.toUtf8().constData(), qrcodegen::QrCode::Ecc::LOW);
const int s=qr.getSize()>0?qr.getSize():1;
const double w=sz.width();
const double h=sz.height();
const double aspect=w/h;
const double size=((aspect>1.0)?h:w);
const double scale=size/(s+2);
// NOTE: For performance reasons my implementation only draws the foreground parts in supplied color.
// It expects background to be prepared already (in white or whatever is preferred).
painter.setPen(Qt::NoPen);
painter.setBrush(fg);
for(int y=0; y<s; y++) {
for(int x=0; x<s; x++) {
const int color=qr.getModule(x, y); // 0 for white, 1 for black
if(0!=color) {
const double rx1=(x+1)*scale, ry1=(y+1)*scale;
QRectF r(rx1, ry1, scale, scale);
painter.drawRects(&r,1);
}
}
}
}
For usage, please see this painter class.
UPDATE 3/3-2016: It has come to my attention that there is a small library project that does what my answer does but in a more "prepackaged" way. You can check it out here.
QR in Qt
There is a small QR-code generator library in pure C and without dependencies, called libqrencode.
Step 1: Install
Before you can use it, you will have to install it. On my Ubuntu 13.10 that meant typing the following in a shell:
sudo aptitude install libqrencode-dev
On other platforms you may have to build it from source by yourself. Simply download the tarball and follow the instructions from the source code download.
Step 2: Project file
Next, you will have to add the library to your project. In my Qt5.2.0 project file (myproject.pro or similar) that meant appending the following line:
LIBS += -lqrencode
This should be similar for most versions of Qt that I know.
Step 3: encode
Next one must write the code that actually uses the library to encode some input string to QR format. That is one line of code:
QRcode *qr=QRcode_encodeString("my string", 1, QR_ECLEVEL_L, QR_MODE_8,0);
NOTE: After experimenting with the parameters I have passed to this function, I have learned that one needs to be careful. Some combinations of parameters failed for no good reason. For example passing 0 as version or using QR_MODE_AN failed with "Invalid parameters". This might be bugs in the ancient version of the library that I am using You have been warned.
Step 4: render image
Finally, before cleaning up, you need to convert the output to bitmap so that it can be rendered on the screen. This is simpler than it sounds. Instead of listing a bunch of assumptions I will instead included my complete working minimalistic QRWidget implementation here. The interesting bits are in the overridden paintEvent() method.
QRWidget.hpp
#ifndef QRWIDGET_HPP
#define QRWIDGET_HPP
#include <QWidget>
class QRWidget : public QWidget{
Q_OBJECT
private:
QString data;
public:
explicit QRWidget(QWidget *parent = 0);
void setQRData(QString data);
protected:
void paintEvent(QPaintEvent *);
};
#endif // QRWIDGET_HPP
QRWidget.cpp
#include "QRWidget.hpp"
#include <QPainter>
#include <QDebug>
#include <qrencode.h>
QRWidget::QRWidget(QWidget *parent) :
QWidget(parent),
data("Hello QR")//Note: The encoding fails with empty string so I just default to something else. Use the setQRData() call to change this.
{
}
void QRWidget::setQRData(QString data){
this->data=data;
update();
}
void QRWidget::paintEvent(QPaintEvent *pe){
QPainter painter(this);
//NOTE: I have hardcoded some parameters here that would make more sense as variables.
QRcode *qr = QRcode_encodeString(data.toStdString().c_str(), 1, QR_ECLEVEL_L, QR_MODE_8, 0);
if(0!=qr){
QColor fg("black");
QColor bg("white");
painter.setBrush(bg);
painter.setPen(Qt::NoPen);
painter.drawRect(0,0,width(),height());
painter.setBrush(fg);
const int s=qr->width>0?qr->width:1;
const double w=width();
const double h=height();
const double aspect=w/h;
const double scale=((aspect>1.0)?h:w)/s;
for(int y=0;y<s;y++){
const int yy=y*s;
for(int x=0;x<s;x++){
const int xx=yy+x;
const unsigned char b=qr->data[xx];
if(b &0x01){
const double rx1=x*scale, ry1=y*scale;
QRectF r(rx1, ry1, scale, scale);
painter.drawRects(&r,1);
}
}
}
QRcode_free(qr);
}
else{
QColor error("red");
painter.setBrush(error);
painter.drawRect(0,0,width(),height());
qDebug()<<"QR FAIL: "<< strerror(errno);
}
qr=0;
}
Summary In this little post I have summarized my experience with getting a QR code generator working with Qt.