Mercurial > hgrepos > Python2 > PyMuPDF
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 | |
| 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 | |
| 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, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'"); | |
| 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> |
