1
0

implement QR code scanning

This commit is contained in:
Sander van Grieken
2022-03-29 16:36:20 +02:00
parent 62009c647e
commit 758a30462e
6 changed files with 221 additions and 44 deletions

View File

@@ -1,25 +1,91 @@
import QtQuick 2.6
import QtQuick 2.12
import QtQuick.Controls 2.0
import QtMultimedia 5.6
Item {
id: scanner
property bool active: false
property string url
property string scanData
property bool _pointsVisible
signal found
VideoOutput {
id: vo
anchors.fill: parent
source: camera
fillMode: VideoOutput.PreserveAspectCrop
Rectangle {
width: parent.width
height: (parent.height - parent.width) / 2
anchors.top: parent.top
color: Qt.rgba(0,0,0,0.5)
}
Rectangle {
width: parent.width
height: (parent.height - parent.width) / 2
anchors.bottom: parent.bottom
color: Qt.rgba(0,0,0,0.5)
}
}
MouseArea {
anchors.fill: parent
onClicked: {
vo.grabToImage(function(result) {
console.log("grab: image=" + (result.image !== undefined) + " url=" + result.url)
if (result.image !== undefined) {
console.log('scanning image for QR')
QR.scanImage(result.image)
}
})
Image {
id: still
anchors.fill: vo
}
SequentialAnimation {
id: foundAnimation
PropertyAction { target: scanner; property: '_pointsVisible'; value: true}
PauseAnimation { duration: 80 }
PropertyAction { target: scanner; property: '_pointsVisible'; value: false}
PauseAnimation { duration: 80 }
PropertyAction { target: scanner; property: '_pointsVisible'; value: true}
PauseAnimation { duration: 80 }
PropertyAction { target: scanner; property: '_pointsVisible'; value: false}
PauseAnimation { duration: 80 }
PropertyAction { target: scanner; property: '_pointsVisible'; value: true}
PauseAnimation { duration: 80 }
PropertyAction { target: scanner; property: '_pointsVisible'; value: false}
PauseAnimation { duration: 80 }
PropertyAction { target: scanner; property: '_pointsVisible'; value: true}
onFinished: found()
}
Component {
id: r
Rectangle {
property int cx
property int cy
width: 15
height: 15
x: cx - width/2
y: cy - height/2
radius: 5
visible: scanner._pointsVisible
}
}
Connections {
target: QR
function onDataChanged() {
console.log(QR.data)
scanner.active = false
scanner.scanData = QR.data
still.source = scanner.url
var sx = still.width/still.sourceSize.width
var sy = still.height/still.sourceSize.height
r.createObject(scanner, {cx: QR.points[0].x * sx, cy: QR.points[0].y * sy, color: 'yellow'})
r.createObject(scanner, {cx: QR.points[1].x * sx, cy: QR.points[1].y * sy, color: 'yellow'})
r.createObject(scanner, {cx: QR.points[2].x * sx, cy: QR.points[2].y * sy, color: 'yellow'})
r.createObject(scanner, {cx: QR.points[3].x * sx, cy: QR.points[3].y * sy, color: 'yellow'})
foundAnimation.start()
}
}
@@ -28,6 +94,12 @@ Item {
deviceId: QtMultimedia.defaultCamera.deviceId
viewfinder.resolution: "640x480"
focus {
focusMode: Camera.FocusContinuous
focusPointMode: Camera.FocusPointCustom
customFocusPoint: Qt.point(0.5, 0.5)
}
function dumpstats() {
console.log(camera.viewfinder.resolution)
console.log(camera.viewfinder.minimumFrameRate)
@@ -36,6 +108,49 @@ Item {
resolutions.forEach(function(item, i) {
console.log('' + item.width + 'x' + item.height)
})
// TODO
// pick a suitable resolution from the available resolutions
// problem: some cameras have no supportedViewfinderResolutions
// but still error out when an invalid resolution is set.
// 640x480 seems to be universally available, but this needs to
// be checked across a range of phone models.
}
}
Timer {
id: scanTimer
interval: 200
repeat: true
running: scanner.active
onTriggered: {
if (QR.busy)
return
vo.grabToImage(function(result) {
if (result.image !== undefined) {
scanner.url = result.url
QR.scanImage(result.image)
} else {
console.log('image grab returned null')
}
})
}
}
Component.onCompleted: {
console.log('Scan page initialized')
QtMultimedia.availableCameras.forEach(function(item) {
console.log('cam found')
console.log(item.deviceId)
console.log(item.displayName)
console.log(item.position)
console.log(item.orientation)
if (QtMultimedia.defaultCamera.deviceId == item.deviceId) {
vo.orientation = item.orientation
}
camera.dumpstats()
})
active = true
}
}

View File

@@ -2,13 +2,25 @@ import QtQuick 2.6
import QtQuick.Controls 2.0
Item {
id: scanPage
property string title: qsTr('Scan')
property bool toolbar: false
property string scanData
signal found
QRScan {
anchors.top: parent.top
anchors.bottom: parent.bottom
width: parent.width
onFound: {
scanPage.scanData = scanData
scanPage.found()
app.stack.pop()
}
}
Button {

View File

@@ -80,7 +80,13 @@ Pane {
Button {
text: qsTr('Scan QR Code')
onClicked: app.stack.push(Qt.resolvedUrl('Scan.qml'))
onClicked: {
var page = app.stack.push(Qt.resolvedUrl('Scan.qml'))
page.onFound.connect(function() {
console.log('got ' + page.scanData)
address.text = page.scanData
})
}
}
}
}