comparison mupdf-source/thirdparty/zxing-cpp/example/ZXingQt6CamReader.qml @ 2:b50eed0cc0ef upstream

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