Prison

qrcodebarcode.cpp
1/*
2 SPDX-FileCopyrightText: 2010-2016 Sune Vuorela <sune@vuorela.dk>
3
4 SPDX-License-Identifier: MIT
5*/
6
7#include "qrcodebarcode_p.h"
8#include <qrencode.h>
9
10#include <memory>
11
12using namespace Prison;
13
14using QRcode_ptr = std::unique_ptr<QRcode, decltype(&QRcode_free)>;
15using QRinput_ptr = std::unique_ptr<QRinput, decltype(&QRinput_free)>;
16
17QRCodeBarcode::QRCodeBarcode()
18 : AbstractBarcodePrivate(Barcode::TwoDimensions)
19{
20}
21QRCodeBarcode::~QRCodeBarcode() = default;
22
23static void qrEncodeString(QRcode_ptr &code, const QByteArray &data)
24{
25 // try decreasing ECC levels, in case the higher levels result in overflowing the maximum content size
26 for (auto ecc : {QR_ECLEVEL_Q, QR_ECLEVEL_M, QR_ECLEVEL_L}) {
27 code.reset(QRcode_encodeString(data.constData(), 0, ecc, QR_MODE_8, true));
28 if (code) {
29 break;
30 }
31 }
32}
33
34QImage QRCodeBarcode::paintImage()
35{
36 QRcode_ptr code(nullptr, &QRcode_free);
37 QRinput_ptr input(nullptr, &QRinput_free);
38 if (m_data.typeId() == QMetaType::QString) {
39 const QByteArray trimmedData(m_data.toString().trimmed().toUtf8());
40 qrEncodeString(code, trimmedData);
41 } else {
42 const auto b = m_data.toByteArray();
43 const auto isReallyBinary = std::any_of(b.begin(), b.end(), [](unsigned char c) {
44 return std::iscntrl(c) && !std::isspace(c);
45 });
46 // prefer encodeString whenever possible, as that selects the more efficient encoding
47 // automatically, otherwise we end up needlessly in the binary encoding unconditionally
48 if (isReallyBinary) {
49 input.reset(QRinput_new());
50 QRinput_append(input.get(), QR_MODE_8, b.size(), reinterpret_cast<const uint8_t *>(b.constData()));
51 code.reset(QRcode_encodeInput(input.get()));
52 } else {
53 qrEncodeString(code, b);
54 }
55 }
56
57 if (!code) {
58 return QImage();
59 }
60 const int margin = 4;
61 /*32 bit colors, 8 bit pr byte*/
62 uchar *img = new uchar[4 * sizeof(char *) * (2 * margin + code->width) * (2 * margin * +code->width)];
63 uchar *p = img;
64 QByteArray background;
65 background.resize(4);
66 background[3] = qAlpha(m_background.rgba());
67 background[2] = qRed(m_background.rgba());
68 background[1] = qGreen(m_background.rgba());
69 background[0] = qBlue(m_background.rgba());
70 QByteArray foreground;
71 foreground.resize(4);
72 foreground[3] = qAlpha(m_foreground.rgba());
73 foreground[2] = qRed(m_foreground.rgba());
74 foreground[1] = qGreen(m_foreground.rgba());
75 foreground[0] = qBlue(m_foreground.rgba());
76 for (int row = 0; row < code->width + 2 * margin; row++) {
77 for (int col = 0; col < code->width + 2 * margin; col++) {
78 if (row < margin || row >= (code->width + margin) || col < margin || col >= (code->width + margin)) {
79 /*4 bytes for color*/
80 for (int i = 0; i < 4; i++) {
81 *p = background[i];
82 p++;
83 }
84 } else {
85 int c = (row - margin) * code->width + (col - margin);
86 /*it is bit 1 that is the interesting bit for us from libqrencode*/
87 if (code->data[c] & 1) {
88 /*4 bytes for color*/
89 for (int i = 0; i < 4; i++) {
90 *p = foreground[i];
91 p++;
92 }
93 } else {
94 /*4 bytes for color*/
95 for (int i = 0; i < 4; i++) {
96 *p = background[i];
97 p++;
98 }
99 }
100 }
101 }
102 }
103
104 const auto result =
105 QImage(img, code->width + 2 * margin, code->width + 2 * margin, QImage::Format_ARGB32).copy(); // deep copy as we are going to delete img
106 delete[] img;
107 return result;
108}
A barcode generator for a fixed barcode format.
Definition barcode.h:40
Provides classes and methods for generating barcodes.
Definition barcode.h:24
const char * constData() const const
void resize(qsizetype newSize, char c)
QImage copy(const QRect &rectangle) const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 18 2024 12:12:17 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.