mirror of https://github.com/status-im/qzxing.git
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:
parent
b9823b7d7f
commit
bec02cb83e
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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:
|
||||||
|
|
11
src/QZXing.h
11
src/QZXing.h
|
@ -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.
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue