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
ApplicationWindow {
id: mainWindow
visible: true
width: 640
height: 480
minimumWidth: formatGroupBox.width +
errorCorrectionlevelGroupBox.width +
sizeGroupBox.width +
6 * advancedOptions.spacing
property bool isAdvancedOptionsEnabled: advancedSwitch.position;
ColumnLayout {
id: mainLayout
anchors {
fill: parent
margins: 10
@ -18,17 +27,110 @@ ApplicationWindow {
selectByMouse: true
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.fillHeight: true
title: "Result barcode image"
border.width: 1
border.color: "#bdbebf"
clip: true
Image{
id:resultImage
anchors.centerIn: parent
source: "image://QZXing/qrcode/" + inputField.text
source: mainLayout.getImageRequestString()
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,
const EncoderFormat encoderFormat,
const QSize encoderImageSize)
const QSize encoderImageSize,
const EncodeErrorCorrectionLevel errorCorrectionLevel)
{
QImage image;
@ -498,7 +499,16 @@ QImage QZXing::encodeData(const QString& data,
switch (encoderFormat) {
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();
const std::vector< std::vector <zxing::byte> >& bytes = bytesRef->getArray();
image = QImage(bytesRef->getWidth(), bytesRef->getHeight(), QImage::Format_ARGB32);
@ -508,7 +518,7 @@ QImage QZXing::encodeData(const QString& data,
qRgb(0,0,0) :
qRgb(255,255,255));
image = image.scaled(240, 240);
image = image.scaled(encoderImageSize);
break;
}
case EncoderFormat_INVALID:

View File

@ -84,6 +84,13 @@ public:
EncoderFormat_QR_CODE
};
enum EncodeErrorCorrectionLevel {
EncodeErrorCorrectionLevel_L = 0,
EncodeErrorCorrectionLevel_M,
EncodeErrorCorrectionLevel_Q,
EncodeErrorCorrectionLevel_H
};
QZXing(QObject *parent = NULL);
~QZXing();
@ -160,8 +167,8 @@ public slots:
*/
static QImage encodeData(const QString& data,
const EncoderFormat encoderFormat = EncoderFormat_QR_CODE,
const QSize encoderImageSize = QSize(240, 240)/*,
const errorcorrectionleve*/);
const QSize encoderImageSize = QSize(240, 240),
const EncodeErrorCorrectionLevel errorCorrectionLevel = EncodeErrorCorrectionLevel_L);
/**
* 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('/');
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();
}
QUrl formatUrl = id.left(slashIndex);
QString encodeFormat = formatUrl.path();
if (encodeFormat != "qrcode") {
qWarning() << "Encoding format" << encodeFormat << "is not supported. Only qrcode is supported";
//Detect operation (ex. encode)
QString operationName = id.left(slashIndex);
if(operationName != "encode")
{
qWarning() << "Operation not supported: " << operationName;
return QImage();
}
QList<QPair<QString, QString>> encodeOptions = QUrlQuery(formatUrl).queryItems();
Q_UNUSED(encodeOptions)
int optionAreaIndex = id.lastIndexOf('?');
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();
return result;
}