Prison

qrcodebarcode.cpp
1 /*
2  SPDX-FileCopyrightText: 2010-2016 Sune Vuorela <[email protected]>
3 
4  SPDX-License-Identifier: MIT
5 */
6 
7 #include "qrcodebarcode.h"
8 #include <qrencode.h>
9 
10 #include <memory>
11 
12 using namespace Prison;
13 
14 using QRcode_ptr = std::unique_ptr<QRcode, decltype(&QRcode_free)>;
15 using QRinput_ptr = std::unique_ptr<QRinput, decltype(&QRinput_free)>;
16 
18  : AbstractBarcode(AbstractBarcode::TwoDimensions)
19 {
20 }
21 QRCodeBarcode::~QRCodeBarcode() = default;
22 
23 static 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 
35 {
36  Q_UNUSED(size);
37 
38  QRcode_ptr code(nullptr, &QRcode_free);
39  QRinput_ptr input(nullptr, &QRinput_free);
40  if (!data().isEmpty()) {
41  const QByteArray trimmedData(data().trimmed().toUtf8());
42  qrEncodeString(code, trimmedData);
43  } else {
44  const auto b = byteArrayData();
45  const auto isReallyBinary = std::any_of(b.begin(), b.end(), [](unsigned char c) {
46  return std::iscntrl(c) && !std::isspace(c);
47  });
48  // prefer encodeString whenever possible, as that selects the more efficient encoding
49  // automatically, otherwise we end up needlessly in the binary encoding unconditionally
50  if (isReallyBinary) {
51  input.reset(QRinput_new());
52  QRinput_append(input.get(), QR_MODE_8, byteArrayData().size(), reinterpret_cast<const uint8_t *>(byteArrayData().constData()));
53  code.reset(QRcode_encodeInput(input.get()));
54  } else {
55  qrEncodeString(code, b);
56  }
57  }
58 
59  if (!code) {
60  return QImage();
61  }
62  const int margin = 4;
63  /*32 bit colors, 8 bit pr byte*/
64  uchar *img = new uchar[4 * sizeof(char *) * (2 * margin + code->width) * (2 * margin * +code->width)];
65  uchar *p = img;
66  QByteArray background;
67  background.resize(4);
68  background[3] = qAlpha(backgroundColor().rgba());
69  background[2] = qRed(backgroundColor().rgba());
70  background[1] = qGreen(backgroundColor().rgba());
71  background[0] = qBlue(backgroundColor().rgba());
72  QByteArray foreground;
73  foreground.resize(4);
74  foreground[3] = qAlpha(foregroundColor().rgba());
75  foreground[2] = qRed(foregroundColor().rgba());
76  foreground[1] = qGreen(foregroundColor().rgba());
77  foreground[0] = qBlue(foregroundColor().rgba());
78  for (int row = 0; row < code->width + 2 * margin; row++) {
79  for (int col = 0; col < code->width + 2 * margin; col++) {
80  if (row < margin || row >= (code->width + margin) || col < margin || col >= (code->width + margin)) {
81  /*4 bytes for color*/
82  for (int i = 0; i < 4; i++) {
83  *p = background[i];
84  p++;
85  }
86  } else {
87  int c = (row - margin) * code->width + (col - margin);
88  /*it is bit 1 that is the interesting bit for us from libqrencode*/
89  if (code->data[c] & 1) {
90  /*4 bytes for color*/
91  for (int i = 0; i < 4; i++) {
92  *p = foreground[i];
93  p++;
94  }
95  } else {
96  /*4 bytes for color*/
97  for (int i = 0; i < 4; i++) {
98  *p = background[i];
99  p++;
100  }
101  }
102  }
103  }
104  }
105 
106  const auto result =
107  QImage(img, code->width + 2 * margin, code->width + 2 * margin, QImage::Format_ARGB32).copy(); // deep copy as we are going to delete img
108  delete[] img;
109  return result;
110 }
QImage paintImage(const QSizeF &size) override
This is the function doing the actual work in generating the barcode.
QRCodeBarcode()
creates a QRCode generator
const QColor & backgroundColor() const
base class for barcode generators To add your own barcode generator, subclass this class and reimplem...
void resize(int size)
const char * constData() const const
QByteArray byteArrayData() const
Binary data encoded in this barcode.
const QColor & foregroundColor() const
QString data() const
Textual content encoded in this barcode.
QImage copy(const QRect &rectangle) const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Tue Dec 5 2023 03:59:26 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.