diff 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
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mupdf-source/thirdparty/zxing-cpp/wrappers/wasm/demo_cam_reader.html	Mon Sep 15 11:43:07 2025 +0200
@@ -0,0 +1,159 @@
+<!DOCTYPE html>
+<html>
+
+<head>
+	<title>zxing-cpp/wasm live demo</title>
+	<link rel="shortcut icon" href="#" />
+	<script src="zxing_reader.js"></script>
+</head>
+
+<body style="text-align: center">
+	<h2>zxing-cpp/wasm live demo</h2>
+	<p>
+		This is a simple demo of the wasm wrapper of <a href="https://github.com/zxing-cpp/zxing-cpp">zxing-cpp</a>
+		scanning for barcodes in a live video stream.
+	</p>
+
+	Camera:
+	<select id="cameraSelector">
+		<option value="user">Front Camera</option>
+		<option value="environment">Back Camera</option>
+	</select>
+	&nbsp;&nbsp;
+
+	Format:
+	<select id="format">
+		<option value="" selected="">Any</option>
+		<option value="Aztec">Aztec</option>
+		<option value="Code39">Codabar</option>
+		<option value="CODE_39">Code39</option>
+		<option value="Code93">Code93</option>
+		<option value="Code128">Code128</option>
+		<option value="DataMatrix">DataMatrix</option>
+		<option value="DataBar">DataBar</option>
+		<option value="DataBarExpanded">DataBarExpanded</option>
+		<option value="DataBarLimited">DataBarLimited</option>
+		<option value="DXFilmEdge">DXFilmEdge</option>
+		<option value="EAN8">EAN-8</option>
+		<option value="EAN13">EAN-13</option>
+		<option value="ITF">ITF</option>
+		<option value="PDF417">PDF417</option>
+		<option value="QRCode">QRCode</option>
+		<option value="MicroQRCode">Micro QRCode</option>
+		<option value="RMQRCode">rMQR Code</option>
+		<option value="UPCA">UPC-A</option>
+		<option value="UPCE">UPC-E</option>
+		<option value="LinearCodes">Linear Codes</option>
+		<option value="MatrixCodes">Matrix Codes</option>
+	</select>
+	&nbsp;&nbsp;
+
+	Mode:
+	<select id="mode">
+		<option value="true" selected="">Normal</option>
+		<option value="false">Fast</option>
+	</select>
+	<br /><br />
+
+	<canvas id="canvas" width="640" height="480"></canvas>
+	<br /><br />
+
+	<div id="result"></div>
+
+	<script>
+		var zxing = ZXing().then(function (instance) {
+			zxing = instance; // this line is supposedly not required but with current emsdk it is :-/
+		});
+
+		const cameraSelector = document.getElementById("cameraSelector");
+		const format = document.getElementById("format");
+		const mode = document.getElementById("mode");
+		const canvas = document.getElementById("canvas");
+		const resultElement = document.getElementById("result");
+
+		const ctx = canvas.getContext("2d", { willReadFrequently: true });
+		const video = document.createElement("video");
+		video.setAttribute("id", "video");
+		video.setAttribute("width", canvas.width);
+		video.setAttribute("height", canvas.height);
+		video.setAttribute("autoplay", "");
+
+		function readBarcodeFromCanvas(canvas, format, mode) {
+			var imgWidth = canvas.width;
+			var imgHeight = canvas.height;
+			var imageData = canvas.getContext('2d').getImageData(0, 0, imgWidth, imgHeight);
+			var sourceBuffer = imageData.data;
+
+			if (zxing != null) {
+				var buffer = zxing._malloc(sourceBuffer.byteLength);
+				zxing.HEAPU8.set(sourceBuffer, buffer);
+				var result = zxing.readBarcodeFromPixmap(buffer, imgWidth, imgHeight, mode, format);
+				zxing._free(buffer);
+				return result;
+			} else {
+				return { error: "ZXing not yet initialized" };
+			}
+		}
+
+		function drawResult(code) {
+			ctx.beginPath();
+			ctx.lineWidth = 4;
+			ctx.strokeStyle = "red";
+			// ctx.textAlign = "center";
+			// ctx.fillStyle = "#green"
+			// ctx.font = "25px Arial";
+			// ctx.fontWeight = "bold";
+			with (code.position) {
+				ctx.moveTo(topLeft.x, topLeft.y);
+				ctx.lineTo(topRight.x, topRight.y);
+				ctx.lineTo(bottomRight.x, bottomRight.y);
+				ctx.lineTo(bottomLeft.x, bottomLeft.y);
+				ctx.lineTo(topLeft.x, topLeft.y);
+				ctx.stroke();
+				// ctx.fillText(code.text, (topLeft.x + bottomRight.x) / 2, (topLeft.y + bottomRight.y) / 2);
+			}
+		}
+
+		function escapeTags(htmlStr) {
+			return htmlStr.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
+		}
+
+		const processFrame = function () {
+			ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
+
+			const code = readBarcodeFromCanvas(canvas, format.value, mode.value === 'true');
+			if (code.format) {
+				resultElement.innerText = code.format + ": " + escapeTags(code.text);
+				drawResult(code)
+			} else {
+				resultElement.innerText = "No barcode found";
+			}
+			requestAnimationFrame(processFrame);
+		};
+
+		const updateVideoStream = function (deviceId) {
+			// To ensure the camera switch, it is advisable to free up the media resources
+			if (video.srcObject) video.srcObject.getTracks().forEach(track => track.stop());
+
+			navigator.mediaDevices
+				.getUserMedia({ video: { facingMode: deviceId }, audio: false })
+				.then(function (stream) {
+					video.srcObject = stream;
+					video.setAttribute("playsinline", true); // required to tell iOS safari we don't want fullscreen
+					video.play();
+					processFrame();
+				})
+				.catch(function (error) {
+					console.error("Error accessing camera:", error);
+				});
+		};
+
+		cameraSelector.addEventListener("change", function () {
+			updateVideoStream(this.value);
+		});
+
+		updateVideoStream();
+	</script>
+</body>
+
+</html>