@codeuctivity/qr-scanner 1.5.0 → 1.5.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,277 +1,269 @@
1
- # QR Scanner
2
-
3
- Javascript QR Code Scanner based on [Cosmo Wolfe's javascript port](https://github.com/cozmo/jsqr) of [Google's ZXing library](https://github.com/zxing/zxing).
4
-
5
- In this library, several improvements have been applied over the original port:
6
-
7
- - Web cam scanning support out of the box
8
- - Uses the browser's native [BarcodeDetector](https://web.dev/shape-detection/) [if available](https://github.com/WICG/shape-detection-api#overview)
9
- - Lightweight: ~59.3 kB (~16.3 kB gzipped) minified with Google's closure compiler. If the native `BarcodeDetector` is available, only ~15.3 kB (~5.6 kB gzipped) are loaded.
10
- - Improved performance and reduced memory footprint.
11
- - Runs in a WebWorker which keeps the main / UI thread responsive.
12
- - Can be configured for better performance on colored QR codes.
13
-
14
- According to [our benchmarking](https://github.com/danimoh/qr-scanner-benchmark) this project's scanner engine's detection rate is about 2-3 times (and up to 8 times) as high as the one of the most popular javascript QR scanner library [LazarSoft/jsqrcode](https://github.com/LazarSoft/jsqrcode). Also the other library oftentimes misreads the content of QR codes, while for this project no misreads occurred in the benchmarking.
15
-
16
- The library supports scanning a continuous video stream from a web cam as well as scanning of single images.
17
-
18
- The development of this library is sponsored by [nimiq](https://www.nimiq.com), world's first browser based blockchain.
19
-
20
- [<img src="https://nimiq.github.io/qr-scanner/nimiq_logo_rgb_horizontal.svg" alt="nimiq.com" width="250">](https://nimiq.com)
21
-
22
-
23
- ## Demo
24
- See [https://nimiq.github.io/qr-scanner/demo/](https://nimiq.github.io/qr-scanner/demo/)
25
-
26
- ## Installation
27
-
28
- Install from npm if you bundle your application:
29
- ```bash
30
- npm install @codeuctivity/qr-scanner
31
- ```
32
-
33
- Then import it from your application code:
34
- ```js
35
- import QrScanner from '@codeuctivity/qr-scanner';
36
- ```
37
-
38
- If you are not using a bundler, copy `qr-scanner.min.js` and `qr-scanner-worker.min.js` from the published package (or a GitHub release) into your project and keep both files next to each other.
39
-
40
- ## Setup
41
-
42
- The QR Scanner consists of two main files. `qr-scanner.min.js` is the main API file which loads the worker script `qr-scanner-worker.min.js` via a dynamic import, only if needed. If you are not using a bundler like Rollup or Webpack that handles dynamic imports automatically, you might have to copy `qr-scanner-worker.min.js` over to your dist, next to `qr-scanner.min.js` or next to the script into which you're bundling `qr-scanner.min.js`.
43
-
44
- `qr-scanner.min.js` is an es6 module and can be imported as follows:
45
- ```js
46
- import QrScanner from 'path/to/qr-scanner.min.js'; // if using plain es6 import
47
- import QrScanner from '@codeuctivity/qr-scanner'; // if installed via package and bundling with a module bundler like webpack or rollup
48
- ```
49
- This requires the importing script to also be an es6 module or a module script tag, e.g.:
50
- ```html
51
- <script type="module">
52
- import QrScanner from 'path/to/qr-scanner.min.js';
53
- // do something with QrScanner
54
- </script>
55
- ```
56
-
57
- If your project is not based on es6 modules you can
58
- - use a [dynamic import](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#Dynamic_Imports) to import the es6 module:
59
- ```js
60
- import('path/to/qr-scanner.min.js').then((module) => {
61
- const QrScanner = module.default;
62
- // do something with QrScanner
63
- });
64
- ```
65
- - use the [UMD build](https://github.com/umdjs/umd) `qr-scanner.umd.min.js` for direct usage as non-module script
66
- ```html
67
- <script src="path/to/qr-scanner.umd.min.js"></script>
68
- <script>
69
- // do something with QrScanner
70
- </script>
71
- ```
72
- - bundle `qr-scanner.umd.min.js` directly with your non-module code with tools like [gulp](https://gulpjs.com/) or [grunt](https://gruntjs.com/).
73
- - bundle the lib with `require` based bundlers like [browserify](https://browserify.org/):
74
- ```js
75
- const QrScanner = require('@codeuctivity/qr-scanner'); // if installed via package
76
- const QrScanner = require('path/to/qr-scanner.umd.min.js'); // if not installed via package
77
- // do something with QrScanner
78
- ```
79
-
80
- This library uses ECMAScript 2017 features like `async` functions. If you need to support old browsers, you can use `qr-scanner.legacy.min.js`, which is ECMAScript 2015 (ES6) compatible. It's a UMD build and can be used as a replacement for `qr-scanner.umd.min.js`, see above. Note, that the legacy build is larger as it includes some polyfills and, to support browsers that don't support dynamic imports, inlines the worker script which however would be needed to be loaded in legacy browsers anyway. You will likely not need to use the legacy build though, as general browser support is already very good for the regular build. Especially if you want to scan from the device's camera, camera support by the browser is the stricter restriction.
81
-
82
- ## Usage
83
-
84
- ### Web Cam Scanning
85
-
86
- #### 1. Create HTML
87
- Create a `<video>` element where the web cam video stream should get rendered:
88
- ```html
89
- <video></video>
90
- ```
91
-
92
- #### 2. Create a QrScanner Instance
93
- ```js
94
- // To enforce the use of the new api with detailed scan results, call the constructor with an options object, see below.
95
- const qrScanner = new QrScanner(
96
- videoElem,
97
- result => console.log('decoded qr code:', result),
98
- { /* your options or returnDetailedScanResult: true if you're not specifying any other options */ },
99
- );
100
-
101
- // For backwards compatibility, omitting the options object will currently use the old api, returning scan results as
102
- // simple strings. This old api will be removed in the next major release, by which point the options object is then
103
- // also not required anymore to enable the new api.
104
- const qrScanner = new QrScanner(
105
- videoElem,
106
- result => console.log('decoded qr code:', result),
107
- // No options provided. This will use the old api and is deprecated in the current version until next major version.
108
- );
109
- ```
110
-
111
- As an optional third parameter an options object can be provided.
112
- Supported options are:
113
-
114
- | Option | Description |
115
- |---|---|
116
- | `onDecodeError` | Handler to be invoked on decoding errors. The default is `QrScanner._onDecodeError`. |
117
- | `preferredCamera` | Preference for the camera to be used. The preference can be either a device id as returned by `listCameras` or a facing mode specified as `'environment'` or `'user'`. The default is `'environment'`. Note that there is no guarantee that the preference can actually be fulfilled. |
118
- | `maxScansPerSecond` | This option can be used to throttle the scans for less battery consumption. The default is 25. [If supported by the browser](https://caniuse.com/mdn-api_htmlvideoelement_requestvideoframecallback), the scan rate is never higher than the camera's frame rate to avoid unnecessary duplicate scans on the same frame. |
119
- | `calculateScanRegion` | A method that determines a region to which scanning should be restricted as a performance improvement. This region can optionally also be scaled down before performing the scan as an additional performance improvement. The region is specified as `x`, `y`, `width` and `height`; the dimensions for the downscaled region as `downScaledWidth` and `downScaledHeight`. Note that the aspect ratio between `width` and `height` and `downScaledWidth` and `downScaledHeight` should remain the same. By default, the scan region is restricted to a centered square of two thirds of the video width or height, whichever is smaller, and scaled down to a 400x400 square. |
120
- | `highlightScanRegion` | Set this option to `true` for rendering an outline around the scan region on the video stream. This uses an absolutely positioned `div` that covers the scan region. This `div` can either be supplied as option `overlay`, see below, or automatically created and then accessed via `qrScanner.$overlay`. It can be freely styled via CSS, e.g. by setting an outline, border, background color, etc. See the [demo](https://nimiq.github.io/qr-scanner/demo/) for examples. |
121
- | `highlightCodeOutline` | Set this option to `true` for rendering an outline around detected QR codes. This uses an absolutely positioned `div` on which an SVG for rendering the outline will be placed. This `div` can either be supplied as option `overlay`, see below, or be accessed via `qrScanner.$overlay`. The SVG can be freely styled via CSS, e.g. by setting the fill color, stroke color, stroke width, etc. See the [demo](https://nimiq.github.io/qr-scanner/demo/) for examples. For more special needs, you can also use the `cornerPoints` directly, see below, for rendering an outline or the points yourself. |
122
- | `overlay` | A custom `div` that can be supplied for use for `highlightScanRegion` and `highlightCodeOutline`. The `div` should be a sibling of `videoElem` in the DOM. If this option is supplied, the default styles for `highlightCodeOutline` are not applied as the expectation is that the element already has some custom style applied to it. |
123
- | `returnDetailedScanResult` | Enforce reporting detailed scan results, see below. |
124
-
125
- To use the default value for an option, omit it or supply `undefined`.
126
-
127
- Results passed to the callback depend on whether an options object was provided:
128
- - If no options object was provided, the result is a string with the read QR code's content. The simple string return type is for backwards compatibility, is now deprecated and will be removed in the future.
129
- - If an options object was provided the result is an object with properties `data` which is the read QR code's string content and `cornerPoints` which are the corner points of the read QR code's outline on the camera stream.
130
-
131
- To avoid usage of the deprecated api if you're not supplying any other options, you can supply `{ returnDetailedScanResult: true }` to enable the new api and get the detailed scan result.
132
-
133
- #### 3. Start scanning
134
- ```js
135
- qrScanner.start();
136
- ```
137
-
138
- Call it when you're ready to scan, for example on a button click or directly on page load.
139
- It will prompt the user for permission to use a camera.
140
- Note: to read from a Web Cam stream, your page must be served via HTTPS.
141
-
142
- #### 4. Stop scanning
143
- ```js
144
- qrScanner.stop();
145
- ```
146
-
147
- If you want, you can stop scanning anytime and resume it by calling `start()` again.
148
-
149
- ### Single Image Scanning
150
-
151
- ```js
152
- QrScanner.scanImage(image)
153
- .then(result => console.log(result))
154
- .catch(error => console.log(error || 'No QR code found.'));
155
- ```
156
- Supported image sources are:
157
- [HTMLImageElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement),
158
- [SVGImageElement](https://developer.mozilla.org/en-US/docs/Web/API/SVGImageElement),
159
- [HTMLVideoElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLVideoElement),
160
- [HTMLCanvasElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement),
161
- [ImageBitmap](https://developer.mozilla.org/en-US/docs/Web/API/ImageBitmap),
162
- [OffscreenCanvas](https://developer.mozilla.org/en-US/docs/Web/API/OffscreenCanvas),
163
- [File](https://developer.mozilla.org/en-US/docs/Web/API/File) / [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob),
164
- [Data URIs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs),
165
- URLs pointing to an image (if they are on the same origin or [CORS enabled](https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_enabled_image))
166
-
167
- As an optional second parameter an options object can be provided.
168
- Supported options are:
169
-
170
- | Option | Description |
171
- |---|---|
172
- | `scanRegion` | A region defined by `x`, `y`, `width` and `height` to which the search for a QR code should be restricted. As a performance improvement this region can be scaled down before performing the scan by providing a `downScaledWidth` and `downScaledHeight`. Note that the aspect ratio between `width` and `height` and `downScaledWidth` and `downScaledHeight` should remain the same. By default, the region spans the whole image and is not scaled down. |
173
- | `qrEngine` | A manually created QR scanner engine instance to be reused. This improves performance if you're scanning a lot of images. An engine can be manually created via `QrScanner.createQrEngine(QrScanner.WORKER_PATH)`. By default, no engine is reused for single image scanning. |
174
- | `canvas` | A manually created canvas to be reused. This improves performance if you're scanning a lot of images. A canvas can be manually created via a `<canvas>` tag in your markup or `document.createElement('canvas')`. By default, no canvas is reused for single image scanning. |
175
- | `disallowCanvasResizing` | Request a provided canvas for reuse to not be resized, irrespective of the source image or source region dimensions. Note that the canvas and source region should have the same aspect ratio to avoid that the image to scan gets distorted which could make detecting QR codes impossible. By default, the canvas size is adapted to the scan region dimensions or down scaled scan region for single image scanning. |
176
- | `alsoTryWithoutScanRegion` | Request a second scan on the entire image if a `scanRegion` was provided and no QR code was found within that region. By default, no second scan is attempted. |
177
- | `returnDetailedScanResult` | Enforce reporting detailed scan results, see below. |
178
-
179
- To use the default value for an option, omit it or supply `undefined`.
180
-
181
- Returned results depend on whether an options object was provided:
182
- - If no options object was provided, the result is a string with the read QR code's content. The simple string return type is for backwards compatibility, is now deprecated and will be removed in the future.
183
- - If an options object was provided the result is an object with properties `data` which is the read QR code's string content and `cornerPoints` which are the corner points of the read QR code's outline on the camera stream.
184
-
185
- To avoid usage of the deprecated api if you're not supplying any other options, you can supply `{ returnDetailedScanResult: true }` to enable the new api and get the detailed scan result.
186
-
187
- If no QR code could be read, `scanImage` throws.
188
-
189
- ### Checking for Camera availability
190
-
191
- This library provides a utility method for checking whether the device has a camera. This can be useful for determining whether to offer the QR web cam scanning functionality to a user.
192
- ```js
193
- QrScanner.hasCamera(); // async
194
- ```
195
-
196
- ### Getting the list of available Cameras
197
-
198
- This library provides a utility method for getting a list of the device's cameras, defined via their `id` and `label`. This can be useful for letting a user choose a specific camera to use.
199
-
200
- You can optionally request the camera's labels. Note that this however requires the user's permission to access the cameras, which he will be asked for if not granted already. If not specifically requested, device labels are determined on a best effort basis, i.e. actual labels are returned if permissions were already granted and fallback labels otherwise. If you want to request camera labels, it's recommendable to call `listCameras` after a QrScanner instance was successfully started, as by then the user will already have given his permission.
201
- ```js
202
- QrScanner.listCameras(); // async; without requesting camera labels
203
- QrScanner.listCameras(true); // async; requesting camera labels, potentially asking the user for permission
204
- ```
205
-
206
- ### Specifying which camera to use
207
-
208
- You can change the preferred camera to be used. The preference can be either a device id as returned by `listCameras` or a facing mode specified as `'environment'` or `'user'`. Note that there is no guarantee that the preference can actually be fulfilled.
209
-
210
- ```js
211
- qrScanner.setCamera(facingModeOrDeviceId); // async
212
- ```
213
-
214
- ### Color Inverted Mode
215
- The scanner by default scans for dark QR codes on a bright background. You can change this behavior to scan for bright QR codes on dark background or for both at the same time:
216
- ```js
217
- qrScanner.setInversionMode(inversionMode);
218
- ```
219
- Where `inversionMode` can be `original`, `invert` or `both`.
220
- The default for web cam scanning is `original` and for single image scanning `both`.
221
-
222
- ### Color Correction
223
- Change the weights for red, green and blue in the grayscale computation to improve contrast for QR codes of a
224
- specific color:
225
-
226
- ```js
227
- qrScanner.setGrayscaleWeights(red, green, blue, useIntegerApproximation = true);
228
- ```
229
- Where `red`, `green` and `blue` should sum up to 256 if `useIntegerApproximation === true` and `1` otherwise. By default, [these](https://en.wikipedia.org/wiki/YUV#Full_swing_for_BT.601) values are used.
230
-
231
- ### Flashlight support
232
-
233
- On supported browsers, you can check whether the currently used camera has a flash and turn it on or off. Note that hasFlash should be called after the scanner was successfully started to avoid the need to open a temporary camera stream just to query whether it has flash support, potentially asking the user for camera access.
234
-
235
- ```js
236
- qrScanner.hasFlash(); // check whether the browser and used camera support turning the flash on; async.
237
- qrScanner.isFlashOn(); // check whether the flash is on
238
- qrScanner.turnFlashOn(); // turn the flash on if supported; async
239
- qrScanner.turnFlashOff(); // turn the flash off if supported; async
240
- qrScanner.toggleFlash(); // toggle the flash if supported; async.
241
- ```
242
-
243
- ### Clean Up
244
-
245
- You can destroy the QR scanner if you don't need it anymore:
246
- ```js
247
- qrScanner.destroy();
248
- qrScanner = null;
249
- ```
250
- This will stop the camera stream and web worker and cleans up event listeners.
251
- The QR scanner will be dysfunctional after it has been destroyed.
252
-
253
- ## Build the project
254
- The project is prebuild in qr-scanner.min.js in combination with qr-scanner-worker.min.js. Building yourself is only necessary if you want to change the code in
255
- the /src folder. NodeJs is required for building.
256
-
257
- Install required build packages:
258
- ```batch
259
- npm install
260
- ```
261
-
262
- Building:
263
- ```batch
264
- npm run build
265
- ```
266
-
267
- ## Integration test
268
-
269
- An end-to-end Playwright test is available to verify webcam-based QR recognition against the fake camera stream in
270
- `playwright/fixtures/VideoOfQrCode.mjpeg`.
271
-
272
- Install dependencies, install the Chromium test browser, then run:
273
-
274
- ```batch
275
- npx playwright install chromium
276
- npm run test:integration
277
- ```
1
+ # QR Scanner
2
+
3
+ JavaScript QR Code Scanner based on [Cosmo Wolfe's javascript port](https://github.com/cozmo/jsqr) of [Google's ZXing library](https://github.com/zxing/zxing); see also the orphaned upstream npm package [`qr-scanner`](https://www.npmjs.com/package/qr-scanner).
4
+
5
+ In this library, several improvements have been applied over the original port:
6
+
7
+ - Web cam scanning support out of the box
8
+ - Uses the browser's native [BarcodeDetector](https://web.dev/shape-detection/) [if available](https://github.com/WICG/shape-detection-api#overview)
9
+ - Lightweight: ~59.3 kB (~16.3 kB gzipped) minified with Google's closure compiler. If the native `BarcodeDetector` is available, only ~15.3 kB (~5.6 kB gzipped) are loaded.
10
+ - Improved performance and reduced memory footprint.
11
+ - Runs in a WebWorker which keeps the main / UI thread responsive.
12
+ - Can be configured for better performance on colored QR codes.
13
+
14
+ According to [our benchmarking](https://github.com/danimoh/qr-scanner-benchmark) this project's scanner engine's detection rate is about 2-3 times (and up to 8 times) as high as the one of the most popular javascript QR scanner library [LazarSoft/jsqrcode](https://github.com/LazarSoft/jsqrcode). Also the other library oftentimes misreads the content of QR codes, while for this project no misreads occurred in the benchmarking.
15
+
16
+ The library supports scanning a continuous video stream from a web cam as well as scanning of single images.
17
+
18
+ ## Installation
19
+
20
+ Install from npm if you bundle your application:
21
+ ```bash
22
+ npm install @codeuctivity/qr-scanner
23
+ ```
24
+
25
+ Then import it from your application code:
26
+ ```js
27
+ import QrScanner from '@codeuctivity/qr-scanner';
28
+ ```
29
+
30
+ If you are not using a bundler, copy `artifacts/qr-scanner.min.js` and `artifacts/qr-scanner-worker.min.js` from the published package (or a GitHub release) into your project and keep both files next to each other.
31
+
32
+ ## Setup
33
+
34
+ The QR Scanner consists of two main files. `artifacts/qr-scanner.min.js` is the main API file which loads the worker script `artifacts/qr-scanner-worker.min.js` via a dynamic import, only if needed. If you are not using a bundler like Rollup or Webpack that handles dynamic imports automatically, you might have to copy `artifacts/qr-scanner-worker.min.js` over to your dist, next to `artifacts/qr-scanner.min.js` or next to the script into which you're bundling `artifacts/qr-scanner.min.js`.
35
+
36
+ `artifacts/qr-scanner.min.js` is an es6 module and can be imported as follows:
37
+ ```js
38
+ import QrScanner from 'path/to/artifacts/qr-scanner.min.js'; // if using plain es6 import
39
+ import QrScanner from '@codeuctivity/qr-scanner'; // if installed via package and bundling with a module bundler like webpack or rollup
40
+ ```
41
+ This requires the importing script to also be an es6 module or a module script tag, e.g.:
42
+ ```html
43
+ <script type="module">
44
+ import QrScanner from 'path/to/artifacts/qr-scanner.min.js';
45
+ // do something with QrScanner
46
+ </script>
47
+ ```
48
+
49
+ If your project is not based on es6 modules you can
50
+ - use a [dynamic import](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#Dynamic_Imports) to import the es6 module:
51
+ ```js
52
+ import('path/to/artifacts/qr-scanner.min.js').then((module) => {
53
+ const QrScanner = module.default;
54
+ // do something with QrScanner
55
+ });
56
+ ```
57
+ - use the [UMD build](https://github.com/umdjs/umd) `artifacts/qr-scanner.umd.min.js` for direct usage as non-module script
58
+ ```html
59
+ <script src="path/to/artifacts/qr-scanner.umd.min.js"></script>
60
+ <script>
61
+ // do something with QrScanner
62
+ </script>
63
+ ```
64
+ - bundle `artifacts/qr-scanner.umd.min.js` directly with your non-module code with tools like [gulp](https://gulpjs.com/) or [grunt](https://gruntjs.com/).
65
+ - bundle the lib with `require` based bundlers like [browserify](https://browserify.org/):
66
+ ```js
67
+ const QrScanner = require('@codeuctivity/qr-scanner'); // if installed via package
68
+ const QrScanner = require('path/to/artifacts/qr-scanner.umd.min.js'); // if not installed via package
69
+ // do something with QrScanner
70
+ ```
71
+
72
+ This library uses ECMAScript 2017 features like `async` functions. If you need to support old browsers, you can use `artifacts/qr-scanner.legacy.min.js`, which is ECMAScript 2015 (ES6) compatible. It's a UMD build and can be used as a replacement for `artifacts/qr-scanner.umd.min.js`, see above. Note that the legacy build is larger because it includes polyfills and, to support browsers that don't support dynamic imports, inlines the worker script which would have to be loaded separately in legacy browsers anyway. You will likely not need to use the legacy build though, as general browser support is already very good for the regular build. Especially if you want to scan from the device's camera, camera support by the browser is the stricter restriction.
73
+
74
+ ## Usage
75
+
76
+ ### Web Cam Scanning
77
+
78
+ #### 1. Create HTML
79
+ Create a `<video>` element where the web cam video stream should get rendered:
80
+ ```html
81
+ <video></video>
82
+ ```
83
+
84
+ #### 2. Create a QrScanner Instance
85
+ ```js
86
+ // To enforce the use of the new api with detailed scan results, call the constructor with an options object, see below.
87
+ const qrScanner = new QrScanner(
88
+ videoElem,
89
+ result => console.log('decoded qr code:', result),
90
+ { /* your options or returnDetailedScanResult: true if you're not specifying any other options */ },
91
+ );
92
+
93
+ // For backwards compatibility, omitting the options object will currently use the old api, returning scan results as
94
+ // simple strings. This old api will be removed in the next major release, by which point the options object is then
95
+ // also not required anymore to enable the new api.
96
+ const qrScanner = new QrScanner(
97
+ videoElem,
98
+ result => console.log('decoded qr code:', result),
99
+ // No options provided. This will use the old api and is deprecated in the current version until next major version.
100
+ );
101
+ ```
102
+
103
+ As an optional third parameter an options object can be provided.
104
+ Supported options are:
105
+
106
+ | Option | Description |
107
+ |---|---|
108
+ | `onDecodeError` | Handler to be invoked on decoding errors. The default is `QrScanner._onDecodeError`. |
109
+ | `preferredCamera` | Preference for the camera to be used. The preference can be either a device id as returned by `listCameras` or a facing mode specified as `'environment'` or `'user'`. The default is `'environment'`. Note that there is no guarantee that the preference can actually be fulfilled. |
110
+ | `maxScansPerSecond` | This option can be used to throttle the scans for less battery consumption. The default is 25. [If supported by the browser](https://caniuse.com/mdn-api_htmlvideoelement_requestvideoframecallback), the scan rate is never higher than the camera's frame rate to avoid unnecessary duplicate scans on the same frame. |
111
+ | `calculateScanRegion` | A method that determines a region to which scanning should be restricted as a performance improvement. This region can optionally also be scaled down before performing the scan as an additional performance improvement. The region is specified as `x`, `y`, `width` and `height`; the dimensions for the downscaled region as `downScaledWidth` and `downScaledHeight`. Note that the aspect ratio between `width` and `height` and `downScaledWidth` and `downScaledHeight` should remain the same. By default, the scan region is restricted to a centered square of two thirds of the video width or height, whichever is smaller, and scaled down to a 400x400 square. |
112
+ | `highlightScanRegion` | Set this option to `true` for rendering an outline around the scan region on the video stream. This uses an absolutely positioned `div` that covers the scan region. This `div` can either be supplied as option `overlay`, see below, or automatically created and then accessed via `qrScanner.$overlay`. It can be freely styled via CSS, e.g. by setting an outline, border, background color, etc. |
113
+ | `highlightCodeOutline` | Set this option to `true` for rendering an outline around detected QR codes. This uses an absolutely positioned `div` on which an SVG for rendering the outline will be placed. This `div` can either be supplied as option `overlay`, see below, or be accessed via `qrScanner.$overlay`. The SVG can be freely styled via CSS, e.g. by setting the fill color, stroke color, stroke width, etc. For more special needs, you can also use the `cornerPoints` directly, see below, for rendering an outline or the points yourself. |
114
+ | `overlay` | A custom `div` that can be supplied for use for `highlightScanRegion` and `highlightCodeOutline`. The `div` should be a sibling of `videoElem` in the DOM. If this option is supplied, the default styles for `highlightCodeOutline` are not applied as the expectation is that the element already has some custom style applied to it. |
115
+ | `returnDetailedScanResult` | Enforce reporting detailed scan results, see below. |
116
+
117
+ To use the default value for an option, omit it or supply `undefined`.
118
+
119
+ Results passed to the callback depend on whether an options object was provided:
120
+ - If no options object was provided, the result is a string with the read QR code's content. The simple string return type is for backwards compatibility, is now deprecated and will be removed in the future.
121
+ - If an options object was provided the result is an object with properties `data` which is the read QR code's string content and `cornerPoints` which are the corner points of the read QR code's outline on the camera stream.
122
+
123
+ To avoid usage of the deprecated api if you're not supplying any other options, you can supply `{ returnDetailedScanResult: true }` to enable the new api and get the detailed scan result.
124
+
125
+ #### 3. Start scanning
126
+ ```js
127
+ qrScanner.start();
128
+ ```
129
+
130
+ Call it when you're ready to scan, for example on a button click or directly on page load.
131
+ It will prompt the user for permission to use a camera.
132
+ Note: to read from a Web Cam stream, your page must be served via HTTPS.
133
+
134
+ #### 4. Stop scanning
135
+ ```js
136
+ qrScanner.stop();
137
+ ```
138
+
139
+ If you want, you can stop scanning anytime and resume it by calling `start()` again.
140
+
141
+ ### Single Image Scanning
142
+
143
+ ```js
144
+ QrScanner.scanImage(image)
145
+ .then(result => console.log(result))
146
+ .catch(error => console.log(error || 'No QR code found.'));
147
+ ```
148
+ Supported image sources are:
149
+ [HTMLImageElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement),
150
+ [SVGImageElement](https://developer.mozilla.org/en-US/docs/Web/API/SVGImageElement),
151
+ [HTMLVideoElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLVideoElement),
152
+ [HTMLCanvasElement](https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement),
153
+ [ImageBitmap](https://developer.mozilla.org/en-US/docs/Web/API/ImageBitmap),
154
+ [OffscreenCanvas](https://developer.mozilla.org/en-US/docs/Web/API/OffscreenCanvas),
155
+ [File](https://developer.mozilla.org/en-US/docs/Web/API/File) / [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob),
156
+ [Data URIs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs),
157
+ URLs pointing to an image (if they are on the same origin or [CORS enabled](https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_enabled_image))
158
+
159
+ As an optional second parameter an options object can be provided.
160
+ Supported options are:
161
+
162
+ | Option | Description |
163
+ |---|---|
164
+ | `scanRegion` | A region defined by `x`, `y`, `width` and `height` to which the search for a QR code should be restricted. As a performance improvement this region can be scaled down before performing the scan by providing a `downScaledWidth` and `downScaledHeight`. Note that the aspect ratio between `width` and `height` and `downScaledWidth` and `downScaledHeight` should remain the same. By default, the region spans the whole image and is not scaled down. |
165
+ | `qrEngine` | A manually created QR scanner engine instance to be reused. This improves performance if you're scanning a lot of images. An engine can be manually created via `QrScanner.createQrEngine(QrScanner.WORKER_PATH)`. By default, no engine is reused for single image scanning. |
166
+ | `canvas` | A manually created canvas to be reused. This improves performance if you're scanning a lot of images. A canvas can be manually created via a `<canvas>` tag in your markup or `document.createElement('canvas')`. By default, no canvas is reused for single image scanning. |
167
+ | `disallowCanvasResizing` | Request a provided canvas for reuse to not be resized, irrespective of the source image or source region dimensions. Note that the canvas and source region should have the same aspect ratio to avoid that the image to scan gets distorted which could make detecting QR codes impossible. By default, the canvas size is adapted to the scan region dimensions or down scaled scan region for single image scanning. |
168
+ | `alsoTryWithoutScanRegion` | Request a second scan on the entire image if a `scanRegion` was provided and no QR code was found within that region. By default, no second scan is attempted. |
169
+ | `returnDetailedScanResult` | Enforce reporting detailed scan results, see below. |
170
+
171
+ To use the default value for an option, omit it or supply `undefined`.
172
+
173
+ Returned results depend on whether an options object was provided:
174
+ - If no options object was provided, the result is a string with the read QR code's content. The simple string return type is for backwards compatibility, is now deprecated and will be removed in the future.
175
+ - If an options object was provided the result is an object with properties `data` which is the read QR code's string content and `cornerPoints` which are the corner points of the read QR code's outline on the camera stream.
176
+
177
+ To avoid usage of the deprecated api if you're not supplying any other options, you can supply `{ returnDetailedScanResult: true }` to enable the new api and get the detailed scan result.
178
+
179
+ If no QR code could be read, `scanImage` throws.
180
+
181
+ ### Checking for Camera availability
182
+
183
+ This library provides a utility method for checking whether the device has a camera. This can be useful for determining whether to offer the QR web cam scanning functionality to a user.
184
+ ```js
185
+ QrScanner.hasCamera(); // async
186
+ ```
187
+
188
+ ### Getting the list of available Cameras
189
+
190
+ This library provides a utility method for getting a list of the device's cameras, defined via their `id` and `label`. This can be useful for letting a user choose a specific camera to use.
191
+
192
+ You can optionally request the camera's labels. Note that this however requires the user's permission to access the cameras, which he will be asked for if not granted already. If not specifically requested, device labels are determined on a best effort basis, i.e. actual labels are returned if permissions were already granted and fallback labels otherwise. If you want to request camera labels, it's recommendable to call `listCameras` after a QrScanner instance was successfully started, as by then the user will already have given his permission.
193
+ ```js
194
+ QrScanner.listCameras(); // async; without requesting camera labels
195
+ QrScanner.listCameras(true); // async; requesting camera labels, potentially asking the user for permission
196
+ ```
197
+
198
+ ### Specifying which camera to use
199
+
200
+ You can change the preferred camera to be used. The preference can be either a device id as returned by `listCameras` or a facing mode specified as `'environment'` or `'user'`. Note that there is no guarantee that the preference can actually be fulfilled.
201
+
202
+ ```js
203
+ qrScanner.setCamera(facingModeOrDeviceId); // async
204
+ ```
205
+
206
+ ### Color Inverted Mode
207
+ The scanner by default scans for dark QR codes on a bright background. You can change this behavior to scan for bright QR codes on dark background or for both at the same time:
208
+ ```js
209
+ qrScanner.setInversionMode(inversionMode);
210
+ ```
211
+ Where `inversionMode` can be `original`, `invert` or `both`.
212
+ The default for web cam scanning is `original` and for single image scanning `both`.
213
+
214
+ ### Color Correction
215
+ Change the weights for red, green and blue in the grayscale computation to improve contrast for QR codes of a
216
+ specific color:
217
+
218
+ ```js
219
+ qrScanner.setGrayscaleWeights(red, green, blue, useIntegerApproximation = true);
220
+ ```
221
+ Where `red`, `green` and `blue` should sum up to 256 if `useIntegerApproximation === true` and `1` otherwise. By default, [these](https://en.wikipedia.org/wiki/YUV#Full_swing_for_BT.601) values are used.
222
+
223
+ ### Flashlight support
224
+
225
+ On supported browsers, you can check whether the currently used camera has a flash and turn it on or off. Note that hasFlash should be called after the scanner was successfully started to avoid the need to open a temporary camera stream just to query whether it has flash support, potentially asking the user for camera access.
226
+
227
+ ```js
228
+ qrScanner.hasFlash(); // check whether the browser and used camera support turning the flash on; async.
229
+ qrScanner.isFlashOn(); // check whether the flash is on
230
+ qrScanner.turnFlashOn(); // turn the flash on if supported; async
231
+ qrScanner.turnFlashOff(); // turn the flash off if supported; async
232
+ qrScanner.toggleFlash(); // toggle the flash if supported; async.
233
+ ```
234
+
235
+ ### Clean Up
236
+
237
+ You can destroy the QR scanner if you don't need it anymore:
238
+ ```js
239
+ qrScanner.destroy();
240
+ qrScanner = null;
241
+ ```
242
+ This will stop the camera stream and web worker and cleans up event listeners.
243
+ The QR scanner will be dysfunctional after it has been destroyed.
244
+
245
+ ## Build the project
246
+ The published npm package (and GitHub releases) include the prebuilt artifacts under `artifacts/` (e.g. `artifacts/qr-scanner.min.js` and `artifacts/qr-scanner-worker.min.js`).
247
+ To generate them locally from this repo checkout (required for the demo and integration tests), run the build steps below. NodeJs is required for building.
248
+
249
+ Install required build packages:
250
+ ```batch
251
+ npm install
252
+ ```
253
+
254
+ Building:
255
+ ```batch
256
+ npm run build
257
+ ```
258
+
259
+ ## Integration test
260
+
261
+ An end-to-end Playwright test is available to verify webcam-based QR recognition against the fake camera stream in
262
+ `playwright/fixtures/VideoOfQrCode.mjpeg`.
263
+
264
+ Install dependencies, install the Chromium test browser, then run:
265
+
266
+ ```batch
267
+ npx playwright install chromium
268
+ npm run test:integration
269
+ ```