barcode-detector 1.0.3 → 2.0.0

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.
Files changed (61) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +251 -63
  3. package/dist/cjs/BarcodeDetector.d.ts +35 -0
  4. package/dist/cjs/index.d.ts +2 -0
  5. package/dist/cjs/index.js +1 -0
  6. package/dist/cjs/package.json +3 -0
  7. package/dist/cjs/pure.d.ts +1 -0
  8. package/dist/cjs/pure.js +3 -0
  9. package/dist/cjs/side-effects.d.ts +24 -0
  10. package/dist/cjs/side-effects.js +1 -0
  11. package/dist/cjs/utils.d.ts +9 -0
  12. package/dist/es/BarcodeDetector.d.ts +35 -0
  13. package/dist/es/index.d.ts +2 -0
  14. package/dist/es/index.js +6 -0
  15. package/dist/es/pure.d.ts +1 -0
  16. package/dist/es/pure.js +2067 -0
  17. package/dist/es/side-effects.d.ts +24 -0
  18. package/dist/es/side-effects.js +6 -0
  19. package/dist/es/utils.d.ts +9 -0
  20. package/dist/iife/index.js +3 -0
  21. package/dist/iife/pure.js +3 -0
  22. package/dist/iife/side-effects.js +3 -0
  23. package/package.json +88 -24
  24. package/.github/workflows/semantic-release.yml +0 -53
  25. package/dist/BarcodeDetector.d.ts +0 -2
  26. package/dist/BarcodeDetectorJsqr.d.ts +0 -10
  27. package/dist/SleepyWorker.d.ts +0 -7
  28. package/dist/barcode-detector.js +0 -2
  29. package/dist/barcode-detector.js.map +0 -1
  30. package/dist/barcode-detector.module.js +0 -2
  31. package/dist/barcode-detector.module.js.map +0 -1
  32. package/dist/barcode-detector.umd.js +0 -2
  33. package/dist/barcode-detector.umd.js.map +0 -1
  34. package/dist/image-data.d.ts +0 -1
  35. package/example_codes/aztec.gif +0 -0
  36. package/example_codes/codabar.png +0 -0
  37. package/example_codes/code_128.gif +0 -0
  38. package/example_codes/code_39.png +0 -0
  39. package/example_codes/code_93.png +0 -0
  40. package/example_codes/data_matrix.png +0 -0
  41. package/example_codes/ean_13.png +0 -0
  42. package/example_codes/ean_8.png +0 -0
  43. package/example_codes/ift.png +0 -0
  44. package/example_codes/multi_qr_code.jpeg +0 -0
  45. package/example_codes/pdf417.png +0 -0
  46. package/example_codes/qr_code.png +0 -0
  47. package/example_codes/upc_a.png +0 -0
  48. package/example_codes/upc_e.png +0 -0
  49. package/example_codes/upca.gif +0 -0
  50. package/example_codes/upca.jpeg +0 -0
  51. package/index.html +0 -81
  52. package/src/BarcodeDetector.ts +0 -3
  53. package/src/BarcodeDetectorJsqr.ts +0 -73
  54. package/src/BarcodeDetectorZXing.ts +0 -114
  55. package/src/SleepyWorker.ts +0 -30
  56. package/src/basic-types.ts +0 -33
  57. package/src/image-data.ts +0 -130
  58. package/src/worker/build.sh +0 -27
  59. package/src/worker/tsconfig.json +0 -6
  60. package/src/worker/worker.ts +0 -57
  61. package/test/Dockerfile +0 -7
@@ -1,114 +0,0 @@
1
- // spec: https://wicg.github.io/shape-detection-api/#barcode-detection-api
2
-
3
- import { BarcodeDetectorOptions, BarcodeFormat, DetectedBarcode } from "./basic-types"
4
- import { imageDataFrom } from "./image-data"
5
- import * as ZXing from "@zxing/library"
6
-
7
- const mapFormat = new Map<BarcodeFormat, ZXing.BarcodeFormat>([
8
-
9
- [ "aztec", ZXing.BarcodeFormat.AZTEC ],
10
- // [ "codabar", ZXing.BarcodeFormat.CODABAR ],
11
- [ "code_39", ZXing.BarcodeFormat.CODE_39 ],
12
- // [ "code_93", ZXing.BarcodeFormat.CODE_93 ],
13
- [ "code_128", ZXing.BarcodeFormat.CODE_128 ],
14
- [ "data_matrix", ZXing.BarcodeFormat.DATA_MATRIX ],
15
- [ "ean_8", ZXing.BarcodeFormat.EAN_8 ],
16
- [ "ean_13", ZXing.BarcodeFormat.EAN_13 ],
17
- [ "itf", ZXing.BarcodeFormat.ITF ],
18
- [ "pdf417", ZXing.BarcodeFormat.PDF_417 ],
19
- [ "qr_code", ZXing.BarcodeFormat.QR_CODE ],
20
- [ "upc_a", ZXing.BarcodeFormat.UPC_A ],
21
- [ "upc_e", ZXing.BarcodeFormat.UPC_E ]
22
-
23
- ])
24
-
25
- const mapFormatInv = new Map<ZXing.BarcodeFormat, BarcodeFormat>(
26
- Array.from(mapFormat).map(([key, val]) => [val, key])
27
- )
28
-
29
- const allSupportedFormats : BarcodeFormat[] = Array.from(mapFormat.keys())
30
-
31
- const mapResult = (result : ZXing.Result) : DetectedBarcode => {
32
- const format = mapFormatInv.get(result.getBarcodeFormat())
33
- const rawValue = result.getText()
34
-
35
- const cornerPoints = Object.freeze(
36
- result
37
- .getResultPoints()
38
- .map(point => ({ x: point.getX(), y: point.getY() }))
39
- )
40
-
41
- const x_min = Math.min(...cornerPoints.map(point => point.x))
42
- const x_max = Math.max(...cornerPoints.map(point => point.x))
43
- const y_min = Math.min(...cornerPoints.map(point => point.y))
44
- const y_max = Math.max(...cornerPoints.map(point => point.y))
45
-
46
- const boundingBox = DOMRectReadOnly.fromRect({
47
- x: x_min,
48
- y: y_min,
49
- width: x_max - x_min,
50
- height: y_max - y_min
51
- })
52
-
53
- return { format, rawValue, cornerPoints, boundingBox }
54
- }
55
-
56
- export default class BarcodeDetector {
57
-
58
- reader : ZXing.MultiFormatReader
59
-
60
- constructor (barcodeDetectorOptions? : BarcodeDetectorOptions) {
61
- // SPEC: A series of BarcodeFormats to search for in the subsequent detect() calls. If not present then the UA SHOULD
62
- // search for all supported formats.
63
- const formats = barcodeDetectorOptions?.formats ?? allSupportedFormats
64
-
65
- // SPEC: If barcodeDetectorOptions.formats is present and empty, then throw a new TypeError.
66
- if (formats.length === 0) {
67
- throw new TypeError("") // TODO pick message
68
- }
69
-
70
- // SPEC: If barcodeDetectorOptions.formats is present and contains unknown, then throw a new TypeError.
71
- if (formats.includes("unknown")) {
72
- throw new TypeError("") // TODO pick message
73
- }
74
-
75
- const hints = new Map([
76
- [ ZXing.DecodeHintType.POSSIBLE_FORMATS, formats.map(format => mapFormat.get(format)) ]
77
- ])
78
-
79
- this.reader = new ZXing.MultiFormatReader()
80
- this.reader.setHints(hints)
81
- }
82
-
83
- static async getSupportedFormats() : Promise<BarcodeFormat[]> {
84
- return allSupportedFormats
85
- }
86
-
87
- // INVESTIGATE:
88
- // * native api on Mac Chrome gives "Source not supported" for Blob
89
- // * only two corner points for code_39
90
- async detect(image : ImageBitmapSource) : Promise<DetectedBarcode[]> {
91
- // TODO: [SPEC]
92
- // Note that if the ImageBitmapSource is an object with either a horizontal dimension or a vertical dimension equal
93
- // to zero, then the Promise will be simply resolved with an empty sequence of detected objects.
94
-
95
- const imageData = await imageDataFrom(image)
96
- const canvas = document.createElement("canvas");
97
- const canvasCtx = canvas.getContext("2d");
98
- canvas.width = imageData.width;
99
- canvas.height = imageData.height;
100
- canvasCtx.putImageData(imageData, 0, 0);
101
-
102
- try {
103
- const luminanceSource = new ZXing.HTMLCanvasElementLuminanceSource(canvas);
104
- const binaryBitmap = new ZXing.BinaryBitmap(new ZXing.HybridBinarizer(luminanceSource));
105
- const result = this.reader.decode(binaryBitmap);
106
-
107
- return [ mapResult(result) ]
108
- } catch (error) {
109
- console.error(error);
110
-
111
- return []
112
- }
113
- }
114
- }
@@ -1,30 +0,0 @@
1
-
2
- export default class SleepyWorker extends EventTarget {
3
- worker? : Worker;
4
- timeout? : number;
5
- stringUrl : string | URL;
6
-
7
- constructor(stringUrl: string | URL) {
8
- super()
9
- this.stringUrl = stringUrl
10
- }
11
-
12
- postMessage(message : any, transfer? : Transferable[]) {
13
- if (this.worker === undefined) {
14
- this.worker = new Worker(this.stringUrl)
15
- this.worker.onmessage = (event : MessageEvent) => {
16
- this.dispatchEvent(new MessageEvent("message", { data: event.data }))
17
- }
18
- } else {
19
- self.clearTimeout(this.timeout)
20
- }
21
-
22
- this.worker.postMessage(message, transfer)
23
-
24
- this.timeout = self.setTimeout(() => {
25
- this.worker.terminate()
26
- this.worker = undefined
27
- }, 2500)
28
- }
29
-
30
- }
@@ -1,33 +0,0 @@
1
- // spec: https://wicg.github.io/shape-detection-api/#barcode-detection-api
2
-
3
- export type BarcodeFormat
4
- = "aztec"
5
- | "code_128"
6
- | "code_39"
7
- | "code_93"
8
- | "codabar"
9
- | "data_matrix"
10
- | "ean_13"
11
- | "ean_8"
12
- | "itf"
13
- | "pdf417"
14
- | "qr_code"
15
- | "upc_a"
16
- | "upc_e"
17
- | "unknown"
18
-
19
- export interface BarcodeDetectorOptions {
20
- formats? : Array<BarcodeFormat>
21
- };
22
-
23
- export interface Point2D {
24
- x : Number,
25
- y : Number
26
- };
27
-
28
- export interface DetectedBarcode {
29
- boundingBox : DOMRectReadOnly,
30
- rawValue : String,
31
- format : BarcodeFormat,
32
- cornerPoints : ReadonlyArray<Point2D>
33
- };
package/src/image-data.ts DELETED
@@ -1,130 +0,0 @@
1
-
2
- function imageDataFromCanvas(image : CanvasImageSource, width : number, height : number) : ImageData {
3
- const canvas = document.createElement("canvas");
4
- const canvasCtx = canvas.getContext("2d");
5
-
6
- canvas.width = width;
7
- canvas.height = height;
8
-
9
- canvasCtx.drawImage(image, 0, 0, width, height);
10
-
11
- return canvasCtx.getImageData(0, 0, width, height);
12
- }
13
-
14
- async function imageDataFromBlob(blob : Blob) : Promise<ImageData> {
15
- // turn blob into an img element and pass back to imageDataFrom
16
- const url = URL.createObjectURL(blob)
17
-
18
- const image = new Image()
19
- image.src = url
20
-
21
- await new Promise((resolve, reject) => {
22
- image.onload = resolve
23
- image.onerror = reject
24
- })
25
-
26
- URL.revokeObjectURL(url)
27
-
28
- return imageDataFrom(image)
29
- }
30
-
31
- export async function imageDataFrom(image : ImageBitmapSource) : Promise<ImageData> {
32
- // spec quoted from:
33
- // https://wicg.github.io/shape-detection-api/#image-sources-for-detection
34
-
35
- // [TODO]
36
- // If any ImageBitmapSource have an effective script origin (origin) which is
37
- // not the same as the Document’s effective script origin, then reject the
38
- // Promise with a new DOMException whose name is SecurityError.
39
-
40
- if (image instanceof HTMLImageElement) {
41
-
42
- // [TODO]
43
- // When an ImageBitmapSource object represents an HTMLImageElement, the
44
- // element’s image must be used as the source image. Specifically, when an
45
- // ImageBitmapSource object represents an animated image in an
46
- // HTMLImageElement, the user agent must use the default image of the
47
- // animation (the one that the format defines is to be used when animation
48
- // is not supported or is disabled), or, if there is no such image, the
49
- // first frame of the animation.
50
-
51
- // [SPEC]
52
- // If the ImageBitmapSource is an HTMLImageElement object that is in the
53
- // Broken (HTML Standard §img-error) state, then reject the Promise with a
54
- // new DOMException whose name is InvalidStateError, and abort any further
55
- // steps.
56
- // [SPEC]
57
- // If the ImageBitmapSource is an HTMLImageElement object that is not fully
58
- // decodable then reject the Promise with a new DOMException whose name is
59
- // InvalidStateError, and abort any further steps
60
- try {
61
- image.decode()
62
- } catch (_) {
63
- throw new DOMException("HTMLImageElement is not decodable", "InvalidStateError")
64
- }
65
-
66
- return imageDataFromCanvas(image, image.naturalWidth, image.naturalHeight)
67
-
68
- } else if (image instanceof SVGImageElement) {
69
-
70
- // TODO width/height is a little bit arbitrary
71
- return imageDataFromCanvas(image, 640, 480)
72
-
73
- } else if (image instanceof HTMLVideoElement) {
74
-
75
- // [SPEC]
76
- // If the ImageBitmapSource is an HTMLVideoElement object whose readyState
77
- // attribute is either HAVE_NOTHING or HAVE_METADATA then reject the Promise
78
- // with a new DOMException whose name is InvalidStateError, and abort any
79
- // further steps.
80
- const HAVE_NOTHING = 0, HAVE_METADATA = 1;
81
- if (image.readyState === HAVE_NOTHING || image.readyState === HAVE_METADATA) {
82
- throw new DOMException("", "InvalidStateError")
83
- }
84
-
85
- // [SPEC]
86
- // When an ImageBitmapSource object represents an HTMLVideoElement, then
87
- // the frame at the current playback position when the method with the
88
- // argument is invoked must be used as the source image when processing the
89
- // image, and the source image’s dimensions must be the intrinsic dimensions
90
- // of the media resource (i.e. after any aspect-ratio correction has been applied).
91
- return imageDataFromCanvas(image, image.videoWidth, image.videoHeight)
92
-
93
- } else if (image instanceof HTMLCanvasElement) {
94
-
95
- // [TODO]
96
- // When an ImageBitmapSource object represents an HTMLCanvasElement, the
97
- // element’s bitmap must be used as the source image.
98
-
99
- // [TODO]
100
- // If the ImageBitmapSource argument is an HTMLCanvasElement whose bitmap’s
101
- // origin-clean (HTML Standard §concept-canvas-origin-clean) flag is false,
102
- // then reject the Promise with a new DOMException whose name is
103
- // SecurityError, and abort any further steps.
104
-
105
- const canvasCtx = image.getContext("2d")
106
- return canvasCtx.getImageData(0, 0, image.width, image.height)
107
-
108
- } else if ('ImageBitmap' in window && image instanceof ImageBitmap) {
109
-
110
- return imageDataFromCanvas(image, image.width, image.height)
111
-
112
- // Can't perform instanceof check when OffscreenCanvas not supported. Thus
113
- // need to feature detect first.
114
- } else if ('OffscreenCanvas' in window && image instanceof OffscreenCanvas) {
115
-
116
- const canvasCtx = image.getContext("2d")
117
- return canvasCtx.getImageData(0, 0, image.width, image.height)
118
-
119
- } else if (image instanceof Blob) {
120
-
121
- return imageDataFromBlob(image)
122
-
123
- } else if (image instanceof ImageData) {
124
-
125
- return image
126
-
127
- } else {
128
- // TODO TypeError?
129
- }
130
- }
@@ -1,27 +0,0 @@
1
- #!/bin/bash
2
-
3
- set +e
4
-
5
- pushd $(dirname $0)
6
-
7
- ../../node_modules/.bin/microbundle \
8
- --entry worker.ts \
9
- --output temp.umd.js \
10
- --format umd \
11
- --tsconfig tsconfig.json \
12
- --sourcemap false \
13
- --generateTypes false \
14
- --external none
15
-
16
- rm -f inline-worker.js
17
- touch inline-worker.js
18
-
19
- echo 'export default URL.createObjectURL(new Blob([`' >> inline-worker.js
20
- cat temp.umd.js >> inline-worker.js
21
- echo '`], { type: "text/javascript" }));' >> inline-worker.js
22
-
23
- rm -f temp.umd.js
24
- # FIXME: don't generate these files:
25
- rm -rf worker
26
-
27
- popd
@@ -1,6 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "sourceMap": false,
4
- "lib": ["esnext", "webworker"],
5
- }
6
- }
@@ -1,57 +0,0 @@
1
- import jsQR, { QRCode } from "jsqr"
2
- import { DetectedBarcode } from "../basic-types"
3
-
4
- declare var self: DedicatedWorkerGlobalScope;
5
- export {};
6
-
7
- function detectWithJsQR(imageData : ImageData) : Array<DetectedBarcode> {
8
- try {
9
- const qrcode : QRCode = jsQR(
10
- imageData.data,
11
- imageData.width,
12
- imageData.height,
13
- { inversionAttempts: "attemptBoth" }
14
- );
15
-
16
- if (qrcode === null || qrcode.data === "") {
17
- return []
18
- } else {
19
- const { location, data } = qrcode
20
-
21
- const cornerPoints = Object.freeze([
22
- location.topLeftCorner,
23
- location.topRightCorner,
24
- location.bottomRightCorner,
25
- location.bottomLeftCorner
26
- ])
27
-
28
- const x1 = Math.min(...cornerPoints.map(point => point.x))
29
- const x2 = Math.max(...cornerPoints.map(point => point.x))
30
- const y1 = Math.min(...cornerPoints.map(point => point.y))
31
- const y2 = Math.max(...cornerPoints.map(point => point.y))
32
-
33
- return [{
34
- boundingBox: DOMRectReadOnly.fromRect({
35
- x: x1,
36
- y: y1,
37
- width: x2 - x1,
38
- height: y2 - y1
39
- }),
40
- rawValue: data,
41
- format: "qr_code",
42
- cornerPoints
43
- }]
44
- }
45
- } catch (error) {
46
- console.error(error)
47
- return []
48
- }
49
- }
50
-
51
- self.addEventListener("message", (event : MessageEvent) => {
52
- const { id, imageData }= event.data
53
-
54
- const detectedBarcodes = detectWithJsQR(imageData)
55
-
56
- self.postMessage({ id, detectedBarcodes })
57
- });
package/test/Dockerfile DELETED
@@ -1,7 +0,0 @@
1
- FROM webplatformtests/wpt:0.46
2
-
3
- RUN ./start.sh
4
- WORKDIR /home/test/web-platform-tests
5
- RUN ./wpt install firefox webdriver
6
-
7
- CMD ["./wpt", "run", "firefox", "shape-detection"]