comparison mupdf-source/thirdparty/zxing-cpp/wrappers/wasm/demo_cam_reader.html @ 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 <!DOCTYPE html>
2 <html>
3
4 <head>
5 <title>zxing-cpp/wasm live demo</title>
6 <link rel="shortcut icon" href="#" />
7 <script src="zxing_reader.js"></script>
8 </head>
9
10 <body style="text-align: center">
11 <h2>zxing-cpp/wasm live demo</h2>
12 <p>
13 This is a simple demo of the wasm wrapper of <a href="https://github.com/zxing-cpp/zxing-cpp">zxing-cpp</a>
14 scanning for barcodes in a live video stream.
15 </p>
16
17 Camera:
18 <select id="cameraSelector">
19 <option value="user">Front Camera</option>
20 <option value="environment">Back Camera</option>
21 </select>
22 &nbsp;&nbsp;
23
24 Format:
25 <select id="format">
26 <option value="" selected="">Any</option>
27 <option value="Aztec">Aztec</option>
28 <option value="Code39">Codabar</option>
29 <option value="CODE_39">Code39</option>
30 <option value="Code93">Code93</option>
31 <option value="Code128">Code128</option>
32 <option value="DataMatrix">DataMatrix</option>
33 <option value="DataBar">DataBar</option>
34 <option value="DataBarExpanded">DataBarExpanded</option>
35 <option value="DataBarLimited">DataBarLimited</option>
36 <option value="DXFilmEdge">DXFilmEdge</option>
37 <option value="EAN8">EAN-8</option>
38 <option value="EAN13">EAN-13</option>
39 <option value="ITF">ITF</option>
40 <option value="PDF417">PDF417</option>
41 <option value="QRCode">QRCode</option>
42 <option value="MicroQRCode">Micro QRCode</option>
43 <option value="RMQRCode">rMQR Code</option>
44 <option value="UPCA">UPC-A</option>
45 <option value="UPCE">UPC-E</option>
46 <option value="LinearCodes">Linear Codes</option>
47 <option value="MatrixCodes">Matrix Codes</option>
48 </select>
49 &nbsp;&nbsp;
50
51 Mode:
52 <select id="mode">
53 <option value="true" selected="">Normal</option>
54 <option value="false">Fast</option>
55 </select>
56 <br /><br />
57
58 <canvas id="canvas" width="640" height="480"></canvas>
59 <br /><br />
60
61 <div id="result"></div>
62
63 <script>
64 var zxing = ZXing().then(function (instance) {
65 zxing = instance; // this line is supposedly not required but with current emsdk it is :-/
66 });
67
68 const cameraSelector = document.getElementById("cameraSelector");
69 const format = document.getElementById("format");
70 const mode = document.getElementById("mode");
71 const canvas = document.getElementById("canvas");
72 const resultElement = document.getElementById("result");
73
74 const ctx = canvas.getContext("2d", { willReadFrequently: true });
75 const video = document.createElement("video");
76 video.setAttribute("id", "video");
77 video.setAttribute("width", canvas.width);
78 video.setAttribute("height", canvas.height);
79 video.setAttribute("autoplay", "");
80
81 function readBarcodeFromCanvas(canvas, format, mode) {
82 var imgWidth = canvas.width;
83 var imgHeight = canvas.height;
84 var imageData = canvas.getContext('2d').getImageData(0, 0, imgWidth, imgHeight);
85 var sourceBuffer = imageData.data;
86
87 if (zxing != null) {
88 var buffer = zxing._malloc(sourceBuffer.byteLength);
89 zxing.HEAPU8.set(sourceBuffer, buffer);
90 var result = zxing.readBarcodeFromPixmap(buffer, imgWidth, imgHeight, mode, format);
91 zxing._free(buffer);
92 return result;
93 } else {
94 return { error: "ZXing not yet initialized" };
95 }
96 }
97
98 function drawResult(code) {
99 ctx.beginPath();
100 ctx.lineWidth = 4;
101 ctx.strokeStyle = "red";
102 // ctx.textAlign = "center";
103 // ctx.fillStyle = "#green"
104 // ctx.font = "25px Arial";
105 // ctx.fontWeight = "bold";
106 with (code.position) {
107 ctx.moveTo(topLeft.x, topLeft.y);
108 ctx.lineTo(topRight.x, topRight.y);
109 ctx.lineTo(bottomRight.x, bottomRight.y);
110 ctx.lineTo(bottomLeft.x, bottomLeft.y);
111 ctx.lineTo(topLeft.x, topLeft.y);
112 ctx.stroke();
113 // ctx.fillText(code.text, (topLeft.x + bottomRight.x) / 2, (topLeft.y + bottomRight.y) / 2);
114 }
115 }
116
117 function escapeTags(htmlStr) {
118 return htmlStr.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
119 }
120
121 const processFrame = function () {
122 ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
123
124 const code = readBarcodeFromCanvas(canvas, format.value, mode.value === 'true');
125 if (code.format) {
126 resultElement.innerText = code.format + ": " + escapeTags(code.text);
127 drawResult(code)
128 } else {
129 resultElement.innerText = "No barcode found";
130 }
131 requestAnimationFrame(processFrame);
132 };
133
134 const updateVideoStream = function (deviceId) {
135 // To ensure the camera switch, it is advisable to free up the media resources
136 if (video.srcObject) video.srcObject.getTracks().forEach(track => track.stop());
137
138 navigator.mediaDevices
139 .getUserMedia({ video: { facingMode: deviceId }, audio: false })
140 .then(function (stream) {
141 video.srcObject = stream;
142 video.setAttribute("playsinline", true); // required to tell iOS safari we don't want fullscreen
143 video.play();
144 processFrame();
145 })
146 .catch(function (error) {
147 console.error("Error accessing camera:", error);
148 });
149 };
150
151 cameraSelector.addEventListener("change", function () {
152 updateVideoStream(this.value);
153 });
154
155 updateVideoStream();
156 </script>
157 </body>
158
159 </html>