diff --git a/examples/BarcodeEncoder/main.qml b/examples/BarcodeEncoder/main.qml index 5063873..4eec536 100644 --- a/examples/BarcodeEncoder/main.qml +++ b/examples/BarcodeEncoder/main.qml @@ -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; + } } } diff --git a/src/QZXing.cpp b/src/QZXing.cpp index ef6544f..385272b 100644 --- a/src/QZXing.cpp +++ b/src/QZXing.cpp @@ -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 barcode = qrcode::Encoder::encode(data.toStdString(), qrcode::ErrorCorrectionLevel::L ); + Ref 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 bytesRef = barcode->getMatrix(); const std::vector< std::vector >& 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: diff --git a/src/QZXing.h b/src/QZXing.h index 25996b3..4b6f603 100644 --- a/src/QZXing.h +++ b/src/QZXing.h @@ -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. diff --git a/src/QZXingImageProvider.cpp b/src/QZXingImageProvider.cpp index abd9c36..206005a 100644 --- a/src/QZXingImageProvider.cpp +++ b/src/QZXingImageProvider.cpp @@ -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 /"; + qWarning() << "Can't parse url" << id << ". Usage is encode?/"; 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> 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; }