1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
|
/*
* Copyright 2022 Axel Waggershauser
*/
// SPDX-License-Identifier: Apache-2.0
import QtQuick
import QtQuick.Window
import QtQuick.Controls
import QtQuick.Layouts
import QtQuick.Shapes
import QtMultimedia
import ZXing
Window {
visible: true
width: 640
height: 480
title: Qt.application.name
property var nullPoints: [Qt.point(0,0), Qt.point(0,0), Qt.point(0,0), Qt.point(0,0)]
property var points: nullPoints
Timer {
id: resetInfo
interval: 1000
}
BarcodeReader {
id: barcodeReader
videoSink: videoOutput.videoSink
formats: (linearSwitch.checked ? (ZXing.LinearCodes) : ZXing.None) | (matrixSwitch.checked ? (ZXing.MatrixCodes) : ZXing.None)
tryRotate: tryRotateSwitch.checked
tryHarder: tryHarderSwitch.checked
tryInvert: tryInvertSwitch.checked
tryDownscale: tryDownscaleSwitch.checked
textMode: ZXing.TextMode.HRI
// callback with parameter 'barcode', called for every successfully processed frame
onFoundBarcode: (barcode)=> {
points = [barcode.position.topLeft, barcode.position.topRight, barcode.position.bottomRight, barcode.position.bottomLeft]
info.text = qsTr("Format: \t %1 \nText: \t %2 \nType: \t %3 \nTime: \t %4 ms").arg(barcode.formatName).arg(barcode.text).arg(barcode.contentTypeName).arg(runTime)
resetInfo.restart()
// console.log(barcode)
}
// called for every processed frame where no barcode was detected
onFailedRead: ()=> {
points = nullPoints
if (!resetInfo.running)
info.text = "No barcode found (in %1 ms)".arg(runTime)
}
}
MediaDevices {
id: devices
}
Camera {
id: camera
cameraDevice: devices.videoInputs[camerasComboBox.currentIndex] ? devices.videoInputs[camerasComboBox.currentIndex] : devices.defaultVideoInput
focusMode: Camera.FocusModeAutoNear
onErrorOccurred: console.log("camera error:" + errorString)
active: true
}
CaptureSession {
id: captureSession
camera: camera
videoOutput: videoOutput
}
ColumnLayout {
anchors.fill: parent
RowLayout {
Layout.fillWidth: true
Layout.fillHeight: false
visible: devices.videoInputs.length > 1
Label {
text: qsTr("Camera: ")
Layout.fillWidth: false
}
ComboBox {
id: camerasComboBox
Layout.fillWidth: true
model: devices.videoInputs
textRole: "description"
currentIndex: 0
}
}
VideoOutput {
id: videoOutput
Layout.fillHeight: true
Layout.fillWidth: true
function mapPointToItem(point)
{
if (videoOutput.sourceRect.width === 0 || videoOutput.sourceRect.height === 0)
return Qt.point(0, 0);
let dx = point.x;
let dy = point.y;
if ((videoOutput.orientation % 180) == 0)
{
dx = dx * videoOutput.contentRect.width / videoOutput.sourceRect.width;
dy = dy * videoOutput.contentRect.height / videoOutput.sourceRect.height;
}
else
{
dx = dx * videoOutput.contentRect.height / videoOutput.sourceRect.height;
dy = dx * videoOutput.contentRect.width / videoOutput.sourceRect.width;
}
switch ((videoOutput.orientation + 360) % 360)
{
case 0:
default:
return Qt.point(videoOutput.contentRect.x + dx, videoOutput.contentRect.y + dy);
case 90:
return Qt.point(videoOutput.contentRect.x + dy, videoOutput.contentRect.y + videoOutput.contentRect.height - dx);
case 180:
return Qt.point(videoOutput.contentRect.x + videoOutput.contentRect.width - dx, videoOutput.contentRect.y + videoOutput.contentRect.height -dy);
case 270:
return Qt.point(videoOutput.contentRect.x + videoOutput.contentRect.width - dy, videoOutput.contentRect.y + dx);
}
}
Shape {
id: polygon
anchors.fill: parent
visible: points.length === 4
ShapePath {
strokeWidth: 3
strokeColor: "red"
strokeStyle: ShapePath.SolidLine
fillColor: "transparent"
//TODO: really? I don't know qml...
startX: videoOutput.mapPointToItem(points[3]).x
startY: videoOutput.mapPointToItem(points[3]).y
PathLine {
x: videoOutput.mapPointToItem(points[0]).x
y: videoOutput.mapPointToItem(points[0]).y
}
PathLine {
x: videoOutput.mapPointToItem(points[1]).x
y: videoOutput.mapPointToItem(points[1]).y
}
PathLine {
x: videoOutput.mapPointToItem(points[2]).x
y: videoOutput.mapPointToItem(points[2]).y
}
PathLine {
x: videoOutput.mapPointToItem(points[3]).x
y: videoOutput.mapPointToItem(points[3]).y
}
}
}
Label {
id: info
color: "white"
padding: 10
background: Rectangle { color: "#80808080" }
}
ColumnLayout {
anchors.right: parent.right
anchors.bottom: parent.bottom
Switch {id: tryRotateSwitch; text: qsTr("Try Rotate"); checked: true }
Switch {id: tryHarderSwitch; text: qsTr("Try Harder"); checked: true }
Switch {id: tryInvertSwitch; text: qsTr("Try Invert"); checked: true }
Switch {id: tryDownscaleSwitch; text: qsTr("Try Downscale"); checked: true }
Switch {id: linearSwitch; text: qsTr("Linear Codes"); checked: true }
Switch {id: matrixSwitch; text: qsTr("Matrix Codes"); checked: true }
}
}
}
}
|