Added new implementation of QrCode encoding.

It is backward compatible with the version that was active till now, though, it also enables an advanced operation for configuring options during encoding.
This commit is contained in:
favoritas37 2018-02-11 20:43:48 +02:00
parent b9823b7d7f
commit bec02cb83e
4 changed files with 181 additions and 17 deletions

View File

@ -3,11 +3,20 @@ import QtQuick.Controls 2.0
import QtQuick.Layouts 1.3 import QtQuick.Layouts 1.3
ApplicationWindow { ApplicationWindow {
id: mainWindow
visible: true visible: true
width: 640 width: 640
height: 480 height: 480
minimumWidth: formatGroupBox.width +
errorCorrectionlevelGroupBox.width +
sizeGroupBox.width +
6 * advancedOptions.spacing
property bool isAdvancedOptionsEnabled: advancedSwitch.position;
ColumnLayout { ColumnLayout {
id: mainLayout
anchors { anchors {
fill: parent fill: parent
margins: 10 margins: 10
@ -18,17 +27,110 @@ ApplicationWindow {
selectByMouse: true selectByMouse: true
text: "Hello world!" text: "Hello world!"
} }
GroupBox {
Row {
Layout.fillWidth: true
Label {
id: resultLabel
text: "Result barcode image"
anchors.verticalCenter: parent.verticalCenter
}
Rectangle {
height: 1
width: parent.width - resultLabel.width - advancedSwitch.width
}
Switch {
id: advancedSwitch
text: "Advanced"
anchors.verticalCenter: parent.verticalCenter
}
}
Row {
id: advancedOptions
Layout.fillWidth: true
visible: mainWindow.isAdvancedOptionsEnabled
clip: true
spacing: 5
GroupBox {
id: formatGroupBox
title: "Format"
anchors.verticalCenter: parent.verticalCenter
ComboBox {
id: formatCombo
model: ["qrcode"]
}
}
GroupBox {
id: errorCorrectionlevelGroupBox
title: "Error Correction Level"
anchors.verticalCenter: parent.verticalCenter
ComboBox {
id: errorCorrectionlevelCombo
model: ["L", "M", "Q", "H"]
}
}
GroupBox {
id: sizeGroupBox
anchors.verticalCenter: parent.verticalCenter
title: "Size"
GridLayout {
RadioButton {
id: radioButtonSize120
text: "120x120"
}
RadioButton {
id: radioButtonSize240
checked: true
text: "240x240"
}
RadioButton {
id: radioButtonSize320
text: "320x320"
}
}
}
}
Rectangle {
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true
title: "Result barcode image" border.width: 1
border.color: "#bdbebf"
clip: true clip: true
Image{ Image{
id:resultImage id:resultImage
anchors.centerIn: parent anchors.centerIn: parent
source: "image://QZXing/qrcode/" + inputField.text
source: mainLayout.getImageRequestString()
cache: false; cache: false;
} }
} }
function getImageRequestString() {
if(mainWindow.isAdvancedOptionsEnabled) {
var width;
var height;
if (radioButtonSize120.checked) {width = "120"; height = "120"}
else if (radioButtonSize240.checked) {width = "240"; height = "240"}
else if (radioButtonSize320.checked) {width = "320"; height = "320"}
return "image://QZXing/encode/" + inputField.text +
"?width="+width+
"&height="+height+
"&corretionLevel=" + errorCorrectionlevelCombo.currentText +
"&format=" + formatCombo.currentText
}
else
return "image://QZXing/encode/" + inputField.text;
}
} }
} }

View File

@ -490,7 +490,8 @@ QString QZXing::decodeSubImageQML(const QUrl &imageUrl,
QImage QZXing::encodeData(const QString& data, QImage QZXing::encodeData(const QString& data,
const EncoderFormat encoderFormat, const EncoderFormat encoderFormat,
const QSize encoderImageSize) const QSize encoderImageSize,
const EncodeErrorCorrectionLevel errorCorrectionLevel)
{ {
QImage image; QImage image;
@ -498,7 +499,16 @@ QImage QZXing::encodeData(const QString& data,
switch (encoderFormat) { switch (encoderFormat) {
case EncoderFormat_QR_CODE: case EncoderFormat_QR_CODE:
{ {
Ref<qrcode::QRCode> barcode = qrcode::Encoder::encode(data.toStdString(), qrcode::ErrorCorrectionLevel::L ); Ref<qrcode::QRCode> barcode = qrcode::Encoder::encode(
data.toStdString(),
errorCorrectionLevel == EncodeErrorCorrectionLevel_H ?
qrcode::ErrorCorrectionLevel::H :
(errorCorrectionLevel == EncodeErrorCorrectionLevel_Q ?
qrcode::ErrorCorrectionLevel::Q :
(errorCorrectionLevel == EncodeErrorCorrectionLevel_M ?
qrcode::ErrorCorrectionLevel::M :
qrcode::ErrorCorrectionLevel::L)));
Ref<qrcode::ByteMatrix> bytesRef = barcode->getMatrix(); Ref<qrcode::ByteMatrix> bytesRef = barcode->getMatrix();
const std::vector< std::vector <zxing::byte> >& bytes = bytesRef->getArray(); const std::vector< std::vector <zxing::byte> >& bytes = bytesRef->getArray();
image = QImage(bytesRef->getWidth(), bytesRef->getHeight(), QImage::Format_ARGB32); image = QImage(bytesRef->getWidth(), bytesRef->getHeight(), QImage::Format_ARGB32);
@ -508,7 +518,7 @@ QImage QZXing::encodeData(const QString& data,
qRgb(0,0,0) : qRgb(0,0,0) :
qRgb(255,255,255)); qRgb(255,255,255));
image = image.scaled(240, 240); image = image.scaled(encoderImageSize);
break; break;
} }
case EncoderFormat_INVALID: case EncoderFormat_INVALID:

View File

@ -84,6 +84,13 @@ public:
EncoderFormat_QR_CODE EncoderFormat_QR_CODE
}; };
enum EncodeErrorCorrectionLevel {
EncodeErrorCorrectionLevel_L = 0,
EncodeErrorCorrectionLevel_M,
EncodeErrorCorrectionLevel_Q,
EncodeErrorCorrectionLevel_H
};
QZXing(QObject *parent = NULL); QZXing(QObject *parent = NULL);
~QZXing(); ~QZXing();
@ -160,8 +167,8 @@ public slots:
*/ */
static QImage encodeData(const QString& data, static QImage encodeData(const QString& data,
const EncoderFormat encoderFormat = EncoderFormat_QR_CODE, const EncoderFormat encoderFormat = EncoderFormat_QR_CODE,
const QSize encoderImageSize = QSize(240, 240)/*, const QSize encoderImageSize = QSize(240, 240),
const errorcorrectionleve*/); const EncodeErrorCorrectionLevel errorCorrectionLevel = EncodeErrorCorrectionLevel_L);
/** /**
* Get the prossecing time in millisecond of the last decode operation. * Get the prossecing time in millisecond of the last decode operation.

View File

@ -11,23 +11,68 @@ QImage QZXingImageProvider::requestImage(const QString &id, QSize *size, const Q
{ {
int slashIndex = id.indexOf('/'); int slashIndex = id.indexOf('/');
if (slashIndex == -1) { if (slashIndex == -1) {
qWarning() << "Can't parse url" << id << ". Usage is <format>/<data>"; qWarning() << "Can't parse url" << id << ". Usage is encode?<format>/<data>";
return QImage(); return QImage();
} }
QUrl formatUrl = id.left(slashIndex); //Detect operation (ex. encode)
QString encodeFormat = formatUrl.path(); QString operationName = id.left(slashIndex);
if (encodeFormat != "qrcode") { if(operationName != "encode")
qWarning() << "Encoding format" << encodeFormat << "is not supported. Only qrcode is supported"; {
qWarning() << "Operation not supported: " << operationName;
return QImage(); return QImage();
} }
QList<QPair<QString, QString>> encodeOptions = QUrlQuery(formatUrl).queryItems(); int optionAreaIndex = id.lastIndexOf('?');
Q_UNUSED(encodeOptions)
QString data = id.mid(slashIndex + 1); QString data;
QImage result;
if(optionAreaIndex >= 0)
{
int startOfDataIndex = slashIndex + 1;
data = id.mid(startOfDataIndex, optionAreaIndex - (startOfDataIndex));
//The dummy option has been added due to a bug(?) of QUrlQuery
// it could not recognize the first key-value pair provided
QUrlQuery optionQuery("options?dummy=&" + id.mid(optionAreaIndex + 1));
QString width = optionQuery.queryItemValue("width");
QString height = optionQuery.queryItemValue("height");
QString corretionLevel = optionQuery.queryItemValue("corretionLevel");
QString format = optionQuery.queryItemValue("format");
if(format != "qrcode")
{
qWarning() << "Format not supported: " << format;
return QImage();
}
if(height.isEmpty() && !width.isEmpty())
height = width;
if(width.isEmpty() && height.isEmpty())
width = height;
QZXing::EncodeErrorCorrectionLevel correctionLevelEnum;
if(corretionLevel == "H")
correctionLevelEnum = QZXing::EncodeErrorCorrectionLevel_H;
else if(corretionLevel == "Q")
correctionLevelEnum = QZXing::EncodeErrorCorrectionLevel_Q;
else if(corretionLevel == "M")
correctionLevelEnum = QZXing::EncodeErrorCorrectionLevel_M;
else
correctionLevelEnum = QZXing::EncodeErrorCorrectionLevel_L;
result = QZXing::encodeData(data, QZXing::EncoderFormat_QR_CODE,
QSize(width.toInt(), height.toInt()),
correctionLevelEnum);
}
else
{
data = id.mid(slashIndex + 1);
result = QZXing::encodeData(data);
}
QImage result = QZXing::encodeData(data);
*size = result.size(); *size = result.size();
return result; return result;
} }