Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

27 Implementation of center image on QR code #51

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ Thumbs.db
*.pro.user*
*.txt.user*
build-*
build

# xemacs temporary files
*.flc
Expand Down
53 changes: 37 additions & 16 deletions examples/QmlBarcodeGenerator/qml/GeneratorPage.qml
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,6 @@ ApplicationWindow {
right: parent.right
}

// TextField {
// id: textField

// anchors.fill: parent

// selectByMouse: true

// placeholderText: qsTr("Input")
// }
CTextField {
id: textField

Expand Down Expand Up @@ -226,7 +217,7 @@ ApplicationWindow {
id: widthField

implicitWidth: parent.width
implicitHeight: parent.height / 8
implicitHeight: parent.height / 10

placeholderText: "Current width: " + barcodeGenerator.width

Expand All @@ -244,7 +235,7 @@ ApplicationWindow {
id: heightField

implicitWidth: parent.width
implicitHeight: parent.height / 8
implicitHeight: parent.height / 10

placeholderText: "Current height: " + barcodeGenerator.height

Expand All @@ -262,7 +253,7 @@ ApplicationWindow {
id: marginField

implicitWidth: parent.width
implicitHeight: parent.height / 8
implicitHeight: parent.height / 10

placeholderText: "Current margin: " + barcodeGenerator.margin

Expand All @@ -280,7 +271,7 @@ ApplicationWindow {
id: eccLevelField

implicitWidth: parent.width
implicitHeight: parent.height / 8
implicitHeight: parent.height / 10

placeholderText: "Current ECC Level: " + barcodeGenerator.eccLevel

Expand All @@ -293,7 +284,7 @@ ApplicationWindow {
id: formatDropDown

implicitWidth: parent.width
implicitHeight: parent.height / 8
implicitHeight: parent.height / 10

model: ListModel {
id: formats
Expand Down Expand Up @@ -350,7 +341,7 @@ ApplicationWindow {
id: imageFormat

implicitWidth: parent.width
implicitHeight: parent.height / 8
implicitHeight: parent.height / 10

model: ListModel {
id: extensions
Expand All @@ -374,12 +365,42 @@ ApplicationWindow {
text: qsTr(barcodeGenerator.fileName)

implicitWidth: parent.width
implicitHeight: parent.height / 8
implicitHeight: parent.height / 10

onEditingFinished: {
barcodeGenerator.fileName = text
}
}

CTextField {
id: imagePathField

text: qsTr(barcodeGenerator.imagePath)

implicitWidth: parent.width
implicitHeight: parent.height / 10

placeholderText: "Current image path: " + barcodeGenerator.imagePath

onEditingFinished: {
barcodeGenerator.imagePath = text
}
}

CTextField {
id: centerImageRatioField

text: qsTr(barcodeGenerator.centerImageRatio.toString())

implicitWidth: parent.width
implicitHeight: parent.height / 10

placeholderText: "Current center image ratio: " + barcodeGenerator.centerImageRatio

onEditingFinished: {
barcodeGenerator.centerImageRatio = parseInt(text)
}
}
}

onClosed: {
Expand Down
102 changes: 96 additions & 6 deletions src/SBarcodeGenerator.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "SBarcodeGenerator.h"
#include <QStandardPaths>
#include <QPainter>

#ifdef Q_OS_ANDROID
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
Expand All @@ -21,19 +22,47 @@ bool SBarcodeGenerator::generate(const QString &inputString)
if (inputString.isEmpty()) {
return false;
} else {
// Change ecc level to max to generate image on QR code.
if (m_format == SCodes::SBarcodeFormat::QRCode && !m_imagePath.isEmpty()) {
if (m_eccLevel < 8) {
qDebug() << "To draw image on QR Code use maximum level of ecc. Setting it to 8.";

m_eccLevel = 8;
emit eccLevelChanged(m_eccLevel);
mateusz-fejcher marked this conversation as resolved.
Show resolved Hide resolved
}
}

ZXing::MultiFormatWriter writer = ZXing::MultiFormatWriter(SCodes::toZXingFormat(m_format)).setMargin(
m_margin).setEccLevel(m_eccLevel);

_bitmap = ZXing::ToMatrix<uint8_t>(writer.encode(inputString.toStdString(), m_width, m_height));
auto qrCodeMatrix = writer.encode(inputString.toStdString(), m_width, m_height);
auto _bitmap = ZXing::ToMatrix<uint8_t>(qrCodeMatrix);
pa-sowa marked this conversation as resolved.
Show resolved Hide resolved

QImage image(_bitmap.data(), m_width, m_height, QImage::Format_Grayscale8);

// Center images works only on QR codes.
if (m_format == SCodes::SBarcodeFormat::QRCode) {
if (!m_imagePath.isEmpty()) {
QSize centerImageSize(m_width / m_centerImageRatio, m_height / m_centerImageRatio);
drawCenterImage(&image, m_imagePath, centerImageSize,
(image.width() - centerImageSize.width()) / 2,
(image.height() - centerImageSize.height()) / 2);
} else {
qDebug() << "Center Image path is empty. Skip drawing center image.";
}
} else {
qDebug() << "Center images works only on QR codes.";
}

m_filePath = QDir::tempPath() + "/" + m_fileName + "." + m_extension;

auto image = QImage(_bitmap.data(), m_width, m_height, QImage::Format::Format_Grayscale8);

QFile file{m_filePath};

if(file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
// Save the final image with the QR code and center image
QFile file(m_filePath);
if (file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
image.save(&file);
} else {
qWarning() << "Could not open file for writing!";
return false;
}

emit generationFinished();
Expand Down Expand Up @@ -82,6 +111,37 @@ bool SBarcodeGenerator::saveImage()
return true;
}

void SBarcodeGenerator::drawCenterImage(QImage *parentImage, QString imagePath, QSize imageSize, int x, int y)
mateusz-fejcher marked this conversation as resolved.
Show resolved Hide resolved
{
QImage centerImage(imageSize, QImage::Format_RGB32);
centerImage.load(imagePath);

if (centerImage.isNull()) {
qWarning() << "Center image could not be loaded!";
return;
}

// Create a painter to overlay the center image on the parentImage.
QPainter painter(parentImage);

// Draw background rectangle.
painter.setBrush(Qt::white);
painter.setPen(Qt::NoPen);
painter.drawRect(x, y, imageSize.width(), imageSize.height());

// Scale the center image to be smaller than background rectangle.
float imageRatio = 0.8;
centerImage = centerImage.scaled(imageSize.width() * imageRatio,
imageSize.height() * imageRatio,
Qt::KeepAspectRatio, Qt::SmoothTransformation);

// Draw image.
painter.drawImage(x + (imageSize.width() - centerImage.width()) / 2,
y + (imageSize.height() - centerImage.height()) / 2,
centerImage);
painter.end();
}

SCodes::SBarcodeFormat SBarcodeGenerator::format() const
{
return m_format;
Expand Down Expand Up @@ -112,3 +172,33 @@ void SBarcodeGenerator::setFormat(const QString &formatName)
{
setFormat(SCodes::fromString(formatName));
}

QString SBarcodeGenerator::imagePath() const
{
return m_imagePath;
}

void SBarcodeGenerator::setImagePath(const QString &imagePath)
{
if (m_imagePath == imagePath) {
return;
}

m_imagePath = imagePath;
emit imagePathChanged();
}

int SBarcodeGenerator::centerImageRatio() const
{
return m_centerImageRatio;
}

void SBarcodeGenerator::setCenterImageRatio(const int &centerImageRatio)
mateusz-fejcher marked this conversation as resolved.
Show resolved Hide resolved
{
if (m_centerImageRatio == centerImageRatio) {
return;
}

m_centerImageRatio = centerImageRatio;
emit centerImageRatioChanged();
}
52 changes: 52 additions & 0 deletions src/SBarcodeGenerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ class SBarcodeGenerator : public QQuickItem
Q_PROPERTY(QString filePath MEMBER m_filePath)
Q_PROPERTY(QString inputText MEMBER m_inputText)
Q_PROPERTY(SCodes::SBarcodeFormat format READ format WRITE setFormat NOTIFY formatChanged)
Q_PROPERTY(QString imagePath READ imagePath WRITE setImagePath NOTIFY imagePathChanged)
Q_PROPERTY(int centerImageRatio READ centerImageRatio WRITE setCenterImageRatio NOTIFY centerImageRatioChanged)

public:

Expand Down Expand Up @@ -56,6 +58,32 @@ class SBarcodeGenerator : public QQuickItem
*/
void setFormat(SCodes::SBarcodeFormat format);

/*!
* \fn QString imagePath() const
* \brief Returns the center image path.
*/
QString imagePath() const;

/*!
* \fn void setImagePath(const QString &imagePath)
* \brief Sets the center image path.
* \param const QString &imagePath - new image path.
*/
void setImagePath(const QString &imagePath);

/*!
* \fn int centerImageRatio() const
* \brief Returns the center image ratio.
*/
int centerImageRatio() const;

/*!
* \fn void setCenterImageRatio(const int &centerImageRatio)
* \brief Sets the center image ratio.
* \param const int &centerImageRatio - new image ratio.
*/
void setCenterImageRatio(const int &centerImageRatio);

public slots:

/*!
Expand Down Expand Up @@ -122,20 +150,44 @@ public slots:
*/
void formatChanged(SCodes::SBarcodeFormat format);

/*!
* \brief This signal is emitted to send image path to QML.
*/
void imagePathChanged();

/*!
* \brief This signal is emitted to send center image ratio to QML.
*/
void centerImageRatioChanged();

private:
int m_width = 500;
int m_height = 500;
int m_margin = 10;
int m_eccLevel = -1;

// centerImageRatio defines the ratio by which the center image is smaller than the QR code.
int m_centerImageRatio = 5;

QString m_extension = "png";
QString m_fileName = "code";
QString m_filePath = "";
QString m_inputText = "";
QString m_imagePath = "";

SCodes::SBarcodeFormat m_format = SCodes::SBarcodeFormat::Code128;

ZXing::Matrix<uint8_t> _bitmap = ZXing::Matrix<uint8_t>();

/*!
* \brief This method draws Rectangle and `imageRatio` smaller Image in the center of that Rectangle.
* \param QImage *parentImage - Image parent. It is used for Painter constructor.
* \param QString imagePath - Image path.
* \param QSize imageSize - Image size.
* \param int x - X coordinate where Image should be painted.
* \param Qint y - Y coordinate where Image should be painted.
*/
void drawCenterImage(QImage *parentImage, QString imagePath, QSize imageSize, int x, int y);
};

#endif // SBARCODEGENERATOR_H