mirror of
https://github.com/serratus/quaggaJS.git
synced 2026-08-13 05:31:37 +08:00
@@ -3,3 +3,4 @@ node_modules/
|
|||||||
coverage/
|
coverage/
|
||||||
.project
|
.project
|
||||||
_site/
|
_site/
|
||||||
|
.idea/
|
||||||
|
|||||||
+7
-2
@@ -48,13 +48,18 @@ module.exports = function(grunt) {
|
|||||||
"glMatrixAddon" : {
|
"glMatrixAddon" : {
|
||||||
"deps" : ["glMatrix"],
|
"deps" : ["glMatrix"],
|
||||||
"exports" : "glMatrixAddon"
|
"exports" : "glMatrixAddon"
|
||||||
|
},
|
||||||
|
"async": {
|
||||||
|
"deps": [],
|
||||||
|
"exports": "async"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
"paths" : {
|
"paths" : {
|
||||||
"typedefs" : "typedefs",
|
"typedefs" : "typedefs",
|
||||||
"glMatrix" : "vendor/glMatrix",
|
"glMatrix" : "vendor/glMatrix",
|
||||||
"glMatrixAddon" : "glMatrixAddon"
|
"glMatrixAddon" : "glMatrixAddon",
|
||||||
|
"async": "vendor/async"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -68,7 +73,7 @@ module.exports = function(grunt) {
|
|||||||
grunt.loadNpmTasks('grunt-requirejs');
|
grunt.loadNpmTasks('grunt-requirejs');
|
||||||
grunt.loadNpmTasks('grunt-karma');
|
grunt.loadNpmTasks('grunt-karma');
|
||||||
// Default task(s).
|
// Default task(s).
|
||||||
grunt.registerTask('default', ['jshint', 'requirejs', 'uglify']);
|
grunt.registerTask('default', ['jshint', 'requirejs']);
|
||||||
grunt.registerTask('test', ['karma']);
|
grunt.registerTask('test', ['karma']);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
quaggaJS
|
quaggaJS
|
||||||
========
|
========
|
||||||
|
|
||||||
|
- [Changelog](#changelog) (2015-01-21)
|
||||||
|
|
||||||
QuaggaJS is a barcode-scanner entirely written in JavaScript supporting real-time localization and decoding of
|
QuaggaJS is a barcode-scanner entirely written in JavaScript supporting real-time localization and decoding of
|
||||||
various types of barcodes such as __EAN__ and __CODE128__. The library is also capable of using `getUserMedia` to get direct
|
various types of barcodes such as __EAN__ and __CODE128__. The library is also capable of using `getUserMedia` to get direct
|
||||||
access to the user's camera stream. Although the code relies on heavy image-processing even recent smartphones are
|
access to the user's camera stream. Although the code relies on heavy image-processing even recent smartphones are
|
||||||
@@ -46,9 +48,9 @@ by simply typing:
|
|||||||
You can check out the [examples](http://serratus.github.io/quaggaJS/examples) to get an idea of how to use QuaggaJS.
|
You can check out the [examples](http://serratus.github.io/quaggaJS/examples) to get an idea of how to use QuaggaJS.
|
||||||
Basically the library exposes the following API:
|
Basically the library exposes the following API:
|
||||||
|
|
||||||
### Quagga.init(config)
|
### Quagga.init(config, callback)
|
||||||
|
|
||||||
This method initializes the library for a given configuration (see below) which also includes a callback function (`readyFunc`) which is called when Quagga is ready to start. The initialization process also requests for camera access if real-time detection is configured.
|
This method initializes the library for a given configuration `config` (see below) and invokes the `callback` when Quagga is ready to start. The initialization process also requests for camera access if real-time detection is configured.
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
Quagga.init({
|
Quagga.init({
|
||||||
@@ -58,12 +60,11 @@ Quagga.init({
|
|||||||
},
|
},
|
||||||
decoder : {
|
decoder : {
|
||||||
readers : ["code_128_reader"]
|
readers : ["code_128_reader"]
|
||||||
},
|
}
|
||||||
readyFunc : function() {
|
}, function() {
|
||||||
console.log("Initialization finished. Ready to start");
|
console.log("Initialization finished. Ready to start");
|
||||||
Quagga.start();
|
Quagga.start();
|
||||||
}
|
});
|
||||||
});
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Quagga.start()
|
### Quagga.start()
|
||||||
@@ -73,18 +74,91 @@ the images.
|
|||||||
|
|
||||||
### Quagga.stop()
|
### Quagga.stop()
|
||||||
|
|
||||||
If the decoder is currently running, after calling `stop()` the decoder does not process any more images.
|
If the decoder is currently running, after calling `stop()` the decoder does not process any more images. Additionally, if a camera-stream was requested upon initialization, this operation also disconnects the camera.
|
||||||
|
|
||||||
|
### Quagga.onProcessed(callback)
|
||||||
|
|
||||||
|
This method registers a `callback(data)` function that is called for each frame after the processing is done. The `data` object contains detailed information about the success/failure of the operation. The output varies, depending whether the detection and/or decoding were successful or not.
|
||||||
|
|
||||||
### Quagga.onDetected(callback)
|
### Quagga.onDetected(callback)
|
||||||
|
|
||||||
Registers a callback function which is triggered whenever a barcode-pattern has been located and decoded
|
Registers a `callback(data)` function which is triggered whenever a barcode-pattern has been located and decoded
|
||||||
successfully. The callback function is called with the decoded data as the first parameter.
|
successfully. The passed `data` object contains information about the decoding process including the detected code which can be obtained by calling `data.codeResult.code`.
|
||||||
|
|
||||||
### Quagga.decodeSingle(config, callback)
|
### Quagga.decodeSingle(config, callback)
|
||||||
|
|
||||||
In contrast to the calls described above, this method does not rely on `getUserMedia` and operates on a
|
In contrast to the calls described above, this method does not rely on `getUserMedia` and operates on a
|
||||||
single image instead. The provided callback is the same as in `onDetected` and contains the decoded data
|
single image instead. The provided callback is the same as in `onDetected` and contains the result `data`
|
||||||
as first parameter.
|
object.
|
||||||
|
|
||||||
|
## <a name="resultobject">The result object</a>
|
||||||
|
|
||||||
|
The callbacks passed into `onProcessed`, `onDetected` and `decodeSingle` receive a `data` object upon execution. The `data` object contains the following information. Depending on the success, some fields may be `undefined` or just empty.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
{
|
||||||
|
"codeResult": {
|
||||||
|
"code": "FANAVF1461710",
|
||||||
|
"start": 355,
|
||||||
|
"end": 26,
|
||||||
|
"codeset": 100,
|
||||||
|
"startInfo": {
|
||||||
|
"error": 1.0000000000000002,
|
||||||
|
"code": 104,
|
||||||
|
"start": 21,
|
||||||
|
"end": 41
|
||||||
|
},
|
||||||
|
"decodedCodes": [{
|
||||||
|
"code": 104,
|
||||||
|
"start": 21,
|
||||||
|
"end": 41
|
||||||
|
},
|
||||||
|
// stripped for brevity
|
||||||
|
{
|
||||||
|
"error": 0.8888888888888893,
|
||||||
|
"code": 106,
|
||||||
|
"start": 328,
|
||||||
|
"end": 350
|
||||||
|
}],
|
||||||
|
"endInfo": {
|
||||||
|
"error": 0.8888888888888893,
|
||||||
|
"code": 106,
|
||||||
|
"start": 328,
|
||||||
|
"end": 350
|
||||||
|
},
|
||||||
|
"direction": -1
|
||||||
|
},
|
||||||
|
"line": [{
|
||||||
|
"x": 25.97278706156836,
|
||||||
|
"y": 360.5616435369468
|
||||||
|
}, {
|
||||||
|
"x": 401.9220519377024,
|
||||||
|
"y": 70.87524989906444
|
||||||
|
}],
|
||||||
|
"angle": -0.6565217179979483,
|
||||||
|
"pattern": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, /* ... */ 1],
|
||||||
|
"box": [
|
||||||
|
[77.4074243622672, 410.9288668804402],
|
||||||
|
[0.050203235235130705, 310.53619724086366],
|
||||||
|
[360.15706727788256, 33.05711026051813],
|
||||||
|
[437.5142884049146, 133.44977990009465]
|
||||||
|
],
|
||||||
|
"boxes": [
|
||||||
|
[
|
||||||
|
[77.4074243622672, 410.9288668804402],
|
||||||
|
[0.050203235235130705, 310.53619724086366],
|
||||||
|
[360.15706727788256, 33.05711026051813],
|
||||||
|
[437.5142884049146, 133.44977990009465]
|
||||||
|
],
|
||||||
|
[
|
||||||
|
[248.90769330706507, 415.2041489551161],
|
||||||
|
[198.9532321622869, 352.62160512937635],
|
||||||
|
[339.546160777576, 240.3979259789976],
|
||||||
|
[389.5006219223542, 302.98046980473737]
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## Config
|
## Config
|
||||||
|
|
||||||
@@ -99,11 +173,13 @@ The default `config` object is set as followed:
|
|||||||
debug: false,
|
debug: false,
|
||||||
controls: false,
|
controls: false,
|
||||||
locate: true,
|
locate: true,
|
||||||
|
numOfWorkers: 4,
|
||||||
|
scriptName: 'quagga.js',
|
||||||
visual: {
|
visual: {
|
||||||
show: true
|
show: true
|
||||||
},
|
},
|
||||||
decoder:{
|
decoder:{
|
||||||
drawBoundingBox: true,
|
drawBoundingBox: false,
|
||||||
showFrequency: false,
|
showFrequency: false,
|
||||||
drawScanline: true,
|
drawScanline: true,
|
||||||
showPattern: false,
|
showPattern: false,
|
||||||
@@ -112,6 +188,7 @@ The default `config` object is set as followed:
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
locator: {
|
locator: {
|
||||||
|
halfSample: true,
|
||||||
showCanvas: false,
|
showCanvas: false,
|
||||||
showPatches: false,
|
showPatches: false,
|
||||||
showFoundPatches: false,
|
showFoundPatches: false,
|
||||||
@@ -151,7 +228,24 @@ Unit Tests can be run with [Karma][karmaUrl] and written using [Mocha][mochaUrl]
|
|||||||
> npm install
|
> npm install
|
||||||
> grunt test
|
> grunt test
|
||||||
```
|
```
|
||||||
|
## Image Debugging
|
||||||
|
|
||||||
|
In case you want to take a deeper dive into the inner workings of Quagga, get to know the _debugging_ capabilities of the current implementation. The various flags exposed through the `config` object give you the abilily to visualize almost every step in the processing. Because of the introduction of the web-workers, and their restriction not to have access to the DOM, the configuration must be explicitly set to `config.numOfWorkers = 0` in order to work.
|
||||||
|
|
||||||
|
## <a name="changelog">Changelog</a>
|
||||||
|
|
||||||
|
### 2015-01-21
|
||||||
|
- Features
|
||||||
|
- Added support for web-worker (using 4 workers as default, can be changed through `config.numOfWorkers`)
|
||||||
|
- Due to the way how web-workers are created, the name of the script file (`config.scriptName`) should be kept in sync with your actual filename
|
||||||
|
- Removed canvas-overlay for decoding (boxes & scanline) which can now be easily implemented using the existing API (see example)
|
||||||
|
- API Changes
|
||||||
|
In the course of implementing web-workers some breaking changes were introduced to the API.
|
||||||
|
- The `Quagga.init` function no longer receives the callback as part of the config but rather as a second argument: `Quagga.init(config, cb)`
|
||||||
|
- The callback to `Quagga.onDetected` now receives an object containing much more information in addition to the decoded code. (see [data](#resultobject))
|
||||||
|
- Added `Quagga.onProcessed(callback)` which provides a way to get information for each image processed.
|
||||||
|
The callback receives the same `data` object as `Quagga.onDetected` does. Depending on the success of the process the `data` object
|
||||||
|
might not contain any `resultCode` and/or `box` properties.
|
||||||
|
|
||||||
[zxing_github]: https://github.com/zxing/zxing
|
[zxing_github]: https://github.com/zxing/zxing
|
||||||
[teaser_left]: https://github.com/serratus/quaggaJS/blob/master/doc/img/mobile-located.png
|
[teaser_left]: https://github.com/serratus/quaggaJS/blob/master/doc/img/mobile-located.png
|
||||||
|
|||||||
Vendored
+1373
-78
File diff suppressed because it is too large
Load Diff
Vendored
-3
File diff suppressed because one or more lines are too long
@@ -27,6 +27,7 @@
|
|||||||
It works best if your camera has built-in auto-focus.
|
It works best if your camera has built-in auto-focus.
|
||||||
</p>
|
</p>
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
|
<button class="stop">Stop</button>
|
||||||
<fieldset class="reader-group">
|
<fieldset class="reader-group">
|
||||||
<label>Code128</label>
|
<label>Code128</label>
|
||||||
<input type="radio" name="reader" value="code_128" checked />
|
<input type="radio" name="reader" value="code_128" checked />
|
||||||
|
|||||||
@@ -8,11 +8,10 @@ $(function() {
|
|||||||
},
|
},
|
||||||
decoder : {
|
decoder : {
|
||||||
readers : ["code_128_reader"]
|
readers : ["code_128_reader"]
|
||||||
},
|
}
|
||||||
readyFunc : function() {
|
}, function() {
|
||||||
App.attachListeners();
|
App.attachListeners();
|
||||||
Quagga.start();
|
Quagga.start();
|
||||||
}
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
attachListeners : function() {
|
attachListeners : function() {
|
||||||
@@ -20,23 +19,55 @@ $(function() {
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
Quagga.setReaders([e.target.value + "_reader"]);
|
Quagga.setReaders([e.target.value + "_reader"]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$(".controls").on("click", "button.stop", function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
Quagga.stop();
|
||||||
|
});
|
||||||
},
|
},
|
||||||
detachListeners : function() {
|
detachListeners : function() {
|
||||||
$(".controls .reader-group").off("change", "input");
|
$(".controls .reader-group").off("change", "input");
|
||||||
|
$(".controls").off("click", "button.stop");
|
||||||
},
|
},
|
||||||
lastResult : null
|
lastResult : null
|
||||||
};
|
};
|
||||||
|
|
||||||
App.init();
|
App.init();
|
||||||
|
|
||||||
|
Quagga.onProcessed(function(result) {
|
||||||
|
var drawingCtx = Quagga.canvas.ctx.overlay,
|
||||||
|
drawingCanvas = Quagga.canvas.dom.overlay;
|
||||||
|
|
||||||
|
if (result) {
|
||||||
|
if (result.boxes) {
|
||||||
|
drawingCtx.clearRect(0, 0, parseInt(drawingCanvas.getAttribute("width")), parseInt(drawingCanvas.getAttribute("height")));
|
||||||
|
result.boxes.filter(function (box) {
|
||||||
|
return box !== result.box;
|
||||||
|
}).forEach(function (box) {
|
||||||
|
Quagga.ImageDebug.drawPath(box, {x: 0, y: 1}, drawingCtx, {color: "green", lineWidth: 2});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.box) {
|
||||||
|
Quagga.ImageDebug.drawPath(result.box, {x: 0, y: 1}, drawingCtx, {color: "#00F", lineWidth: 2});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.codeResult && result.codeResult.code) {
|
||||||
|
Quagga.ImageDebug.drawPath(result.line, {x: 'x', y: 'y'}, drawingCtx, {color: 'red', lineWidth: 3});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
Quagga.onDetected(function(result) {
|
Quagga.onDetected(function(result) {
|
||||||
if (App.lastResult !== result) {
|
var code = result.codeResult.code;
|
||||||
App.lastResult = result;
|
|
||||||
|
if (App.lastResult !== code) {
|
||||||
|
App.lastResult = code;
|
||||||
var $node = null, canvas = Quagga.canvas.dom.image;
|
var $node = null, canvas = Quagga.canvas.dom.image;
|
||||||
|
|
||||||
$node = $('<li><div class="thumbnail"><div class="imgWrapper"><img /></div><div class="caption"><h4 class="code"></h4></div></div></li>');
|
$node = $('<li><div class="thumbnail"><div class="imgWrapper"><img /></div><div class="caption"><h4 class="code"></h4></div></div></li>');
|
||||||
$node.find("img").attr("src", canvas.toDataURL());
|
$node.find("img").attr("src", canvas.toDataURL());
|
||||||
$node.find("h4.code").html(result);
|
$node.find("h4.code").html(code);
|
||||||
$("#result_strip ul.thumbnails").prepend($node);
|
$("#result_strip ul.thumbnails").prepend($node);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -41,6 +41,7 @@
|
|||||||
<ul class="thumbnails"></ul>
|
<ul class="thumbnails"></ul>
|
||||||
</div>
|
</div>
|
||||||
<div id="interactive" class="viewport"></div>
|
<div id="interactive" class="viewport"></div>
|
||||||
|
<div id="debug"></div>
|
||||||
</section>
|
</section>
|
||||||
<footer>
|
<footer>
|
||||||
<p>
|
<p>
|
||||||
|
|||||||
@@ -4,16 +4,15 @@ $(function() {
|
|||||||
Quagga.init({
|
Quagga.init({
|
||||||
inputStream: { name: "Test",
|
inputStream: { name: "Test",
|
||||||
type: "ImageStream",
|
type: "ImageStream",
|
||||||
src: "/test/fixtures/" + App.config.reader + "/",
|
src: "../test/fixtures/" + App.config.reader + "/",
|
||||||
length: App.config.length
|
length: App.config.length
|
||||||
},
|
},
|
||||||
decoder : {
|
decoder : {
|
||||||
readers : [App.config.reader + "_reader"]
|
readers : [App.config.reader + "_reader"]
|
||||||
},
|
}
|
||||||
readyFunc : function() {
|
}, function() {
|
||||||
App.attachListeners();
|
App.attachListeners();
|
||||||
Quagga.start();
|
Quagga.start();
|
||||||
}
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
config: {
|
config: {
|
||||||
@@ -42,12 +41,38 @@ $(function() {
|
|||||||
|
|
||||||
App.init();
|
App.init();
|
||||||
|
|
||||||
|
Quagga.onProcessed(function(result) {
|
||||||
|
var drawingCtx = Quagga.canvas.ctx.overlay,
|
||||||
|
drawingCanvas = Quagga.canvas.dom.overlay;
|
||||||
|
|
||||||
|
if (result) {
|
||||||
|
if (result.boxes) {
|
||||||
|
drawingCtx.clearRect(0, 0, parseInt(drawingCanvas.getAttribute("width")), parseInt(drawingCanvas.getAttribute("height")));
|
||||||
|
result.boxes.filter(function (box) {
|
||||||
|
return box !== result.box;
|
||||||
|
}).forEach(function (box) {
|
||||||
|
Quagga.ImageDebug.drawPath(box, {x: 0, y: 1}, drawingCtx, {color: "green", lineWidth: 2});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.box) {
|
||||||
|
Quagga.ImageDebug.drawPath(result.box, {x: 0, y: 1}, drawingCtx, {color: "#00F", lineWidth: 2});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.codeResult && result.codeResult.code) {
|
||||||
|
Quagga.ImageDebug.drawPath(result.line, {x: 'x', y: 'y'}, drawingCtx, {color: 'red', lineWidth: 3});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
Quagga.onDetected(function(result) {
|
Quagga.onDetected(function(result) {
|
||||||
var $node = null, canvas = Quagga.canvas.dom.image;
|
var $node,
|
||||||
|
canvas = Quagga.canvas.dom.image,
|
||||||
|
detectedCode = result.codeResult.code;
|
||||||
|
|
||||||
$node = $('<li><div class="thumbnail"><div class="imgWrapper"><img /></div><div class="caption"><h4 class="code"></h4></div></div></li>');
|
$node = $('<li><div class="thumbnail"><div class="imgWrapper"><img /></div><div class="caption"><h4 class="code"></h4></div></div></li>');
|
||||||
$node.find("img").attr("src", canvas.toDataURL());
|
$node.find("img").attr("src", canvas.toDataURL());
|
||||||
$node.find("h4.code").html(result);
|
$node.find("h4.code").html(detectedCode);
|
||||||
$("#result_strip ul.thumbnails").prepend($node);
|
$("#result_strip ul.thumbnails").prepend($node);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -30,6 +30,7 @@ define(["bresenham", "image_debug", 'code_128_reader', 'ean_reader'], function(B
|
|||||||
initConfig();
|
initConfig();
|
||||||
|
|
||||||
function initCanvas() {
|
function initCanvas() {
|
||||||
|
if (typeof document !== 'undefined') {
|
||||||
var $debug = document.querySelector("#debug.detection");
|
var $debug = document.querySelector("#debug.detection");
|
||||||
_canvas.dom.frequency = document.querySelector("canvas.frequency");
|
_canvas.dom.frequency = document.querySelector("canvas.frequency");
|
||||||
if (!_canvas.dom.frequency) {
|
if (!_canvas.dom.frequency) {
|
||||||
@@ -56,6 +57,7 @@ define(["bresenham", "image_debug", 'code_128_reader', 'ean_reader'], function(B
|
|||||||
_canvas.ctx.overlay = _canvas.dom.overlay.getContext("2d");
|
_canvas.ctx.overlay = _canvas.dom.overlay.getContext("2d");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function initReaders() {
|
function initReaders() {
|
||||||
var i;
|
var i;
|
||||||
@@ -66,6 +68,7 @@ define(["bresenham", "image_debug", 'code_128_reader', 'ean_reader'], function(B
|
|||||||
}
|
}
|
||||||
|
|
||||||
function initConfig() {
|
function initConfig() {
|
||||||
|
if (typeof document !== 'undefined') {
|
||||||
var i,
|
var i,
|
||||||
vis = [{
|
vis = [{
|
||||||
node : _canvas.dom.frequency,
|
node : _canvas.dom.frequency,
|
||||||
@@ -83,6 +86,7 @@ define(["bresenham", "image_debug", 'code_128_reader', 'ean_reader'], function(B
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* extend the line on both ends
|
* extend the line on both ends
|
||||||
@@ -235,6 +239,7 @@ define(["bresenham", "image_debug", 'code_128_reader', 'ean_reader'], function(B
|
|||||||
for ( i = 0; i < boxes.length; i++) {
|
for ( i = 0; i < boxes.length; i++) {
|
||||||
result = decodeFromBoundingBox(boxes[i]);
|
result = decodeFromBoundingBox(boxes[i]);
|
||||||
if (result && result.codeResult) {
|
if (result && result.codeResult) {
|
||||||
|
result.box = boxes[i];
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+16
-13
@@ -14,7 +14,6 @@ function(ImageWrapper, CVUtils, Rasterizer, Tracer, skeletonizer, ArrayHelper, I
|
|||||||
_patchLabelGrid,
|
_patchLabelGrid,
|
||||||
_imageToPatchGrid,
|
_imageToPatchGrid,
|
||||||
_binaryImageWrapper,
|
_binaryImageWrapper,
|
||||||
_halfSample = true,
|
|
||||||
_patchSize,
|
_patchSize,
|
||||||
_canvasContainer = {
|
_canvasContainer = {
|
||||||
ctx : {
|
ctx : {
|
||||||
@@ -26,12 +25,13 @@ function(ImageWrapper, CVUtils, Rasterizer, Tracer, skeletonizer, ArrayHelper, I
|
|||||||
},
|
},
|
||||||
_numPatches = {x: 0, y: 0},
|
_numPatches = {x: 0, y: 0},
|
||||||
_inputImageWrapper,
|
_inputImageWrapper,
|
||||||
_skeletonizer;
|
_skeletonizer,
|
||||||
|
self = this;
|
||||||
|
|
||||||
function initBuffers() {
|
function initBuffers() {
|
||||||
var skeletonImageData;
|
var skeletonImageData;
|
||||||
|
|
||||||
if (_halfSample) {
|
if (_config.halfSample) {
|
||||||
_currentImageWrapper = new ImageWrapper({
|
_currentImageWrapper = new ImageWrapper({
|
||||||
x : _inputImageWrapper.size.x / 2 | 0,
|
x : _inputImageWrapper.size.x / 2 | 0,
|
||||||
y : _inputImageWrapper.size.y / 2 | 0
|
y : _inputImageWrapper.size.y / 2 | 0
|
||||||
@@ -41,8 +41,8 @@ function(ImageWrapper, CVUtils, Rasterizer, Tracer, skeletonizer, ArrayHelper, I
|
|||||||
}
|
}
|
||||||
|
|
||||||
_patchSize = {
|
_patchSize = {
|
||||||
x : 16 * ( _halfSample ? 1 : 2),
|
x : 16 * ( _config.halfSample ? 1 : 2),
|
||||||
y : 16 * ( _halfSample ? 1 : 2)
|
y : 16 * ( _config.halfSample ? 1 : 2)
|
||||||
};
|
};
|
||||||
|
|
||||||
_numPatches.x = _currentImageWrapper.size.x / _patchSize.x | 0;
|
_numPatches.x = _currentImageWrapper.size.x / _patchSize.x | 0;
|
||||||
@@ -52,10 +52,10 @@ function(ImageWrapper, CVUtils, Rasterizer, Tracer, skeletonizer, ArrayHelper, I
|
|||||||
|
|
||||||
_labelImageWrapper = new ImageWrapper(_patchSize, undefined, Array, true);
|
_labelImageWrapper = new ImageWrapper(_patchSize, undefined, Array, true);
|
||||||
|
|
||||||
skeletonImageData = new ArrayBuffer(_patchSize.x * _patchSize.y * 16);
|
skeletonImageData = new ArrayBuffer(64*1024);
|
||||||
_subImageWrapper = new ImageWrapper(_patchSize, new Uint8Array(skeletonImageData, 0, _patchSize.x * _patchSize.y));
|
_subImageWrapper = new ImageWrapper(_patchSize, new Uint8Array(skeletonImageData, 0, _patchSize.x * _patchSize.y));
|
||||||
_skelImageWrapper = new ImageWrapper(_patchSize, new Uint8Array(skeletonImageData, _patchSize.x * _patchSize.y * 3, _patchSize.x * _patchSize.y), undefined, true);
|
_skelImageWrapper = new ImageWrapper(_patchSize, new Uint8Array(skeletonImageData, _patchSize.x * _patchSize.y * 3, _patchSize.x * _patchSize.y), undefined, true);
|
||||||
_skeletonizer = skeletonizer(window, {
|
_skeletonizer = skeletonizer(self, {
|
||||||
size : _patchSize.x
|
size : _patchSize.x
|
||||||
}, skeletonImageData);
|
}, skeletonImageData);
|
||||||
|
|
||||||
@@ -68,6 +68,9 @@ function(ImageWrapper, CVUtils, Rasterizer, Tracer, skeletonizer, ArrayHelper, I
|
|||||||
}
|
}
|
||||||
|
|
||||||
function initCanvas() {
|
function initCanvas() {
|
||||||
|
if (_config.useWorker || typeof document === 'undefined') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
_canvasContainer.dom.binary = document.createElement("canvas");
|
_canvasContainer.dom.binary = document.createElement("canvas");
|
||||||
_canvasContainer.dom.binary.className = "binaryBuffer";
|
_canvasContainer.dom.binary.className = "binaryBuffer";
|
||||||
if (_config.showCanvas === true) {
|
if (_config.showCanvas === true) {
|
||||||
@@ -142,7 +145,7 @@ function(ImageWrapper, CVUtils, Rasterizer, Tracer, skeletonizer, ArrayHelper, I
|
|||||||
ImageDebug.drawPath(box, {x: 0, y: 1}, _canvasContainer.ctx.binary, {color: '#ff0000', lineWidth: 2});
|
ImageDebug.drawPath(box, {x: 0, y: 1}, _canvasContainer.ctx.binary, {color: '#ff0000', lineWidth: 2});
|
||||||
}
|
}
|
||||||
|
|
||||||
scale = _halfSample ? 2 : 1;
|
scale = _config.halfSample ? 2 : 1;
|
||||||
// reverse rotation;
|
// reverse rotation;
|
||||||
transMat = mat2.inverse(transMat);
|
transMat = mat2.inverse(transMat);
|
||||||
for ( j = 0; j < 4; j++) {
|
for ( j = 0; j < 4; j++) {
|
||||||
@@ -472,9 +475,10 @@ function(ImageWrapper, CVUtils, Rasterizer, Tracer, skeletonizer, ArrayHelper, I
|
|||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
init : function(config, data) {
|
init : function(inputImageWrapper, config) {
|
||||||
_config = config;
|
_config = config;
|
||||||
_inputImageWrapper = data.inputImageWrapper;
|
_inputImageWrapper = inputImageWrapper;
|
||||||
|
|
||||||
initBuffers();
|
initBuffers();
|
||||||
initCanvas();
|
initCanvas();
|
||||||
},
|
},
|
||||||
@@ -483,7 +487,7 @@ function(ImageWrapper, CVUtils, Rasterizer, Tracer, skeletonizer, ArrayHelper, I
|
|||||||
topLabels = [],
|
topLabels = [],
|
||||||
boxes = [];
|
boxes = [];
|
||||||
|
|
||||||
if (_halfSample) {
|
if (_config.halfSample) {
|
||||||
CVUtils.halfSample(_inputImageWrapper, _currentImageWrapper);
|
CVUtils.halfSample(_inputImageWrapper, _currentImageWrapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -491,7 +495,7 @@ function(ImageWrapper, CVUtils, Rasterizer, Tracer, skeletonizer, ArrayHelper, I
|
|||||||
patchesFound = findPatches();
|
patchesFound = findPatches();
|
||||||
// return unless 5% or more patches are found
|
// return unless 5% or more patches are found
|
||||||
if (patchesFound.length < _numPatches.x * _numPatches.y * 0.05) {
|
if (patchesFound.length < _numPatches.x * _numPatches.y * 0.05) {
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// rasterrize area by comparing angular similarity;
|
// rasterrize area by comparing angular similarity;
|
||||||
@@ -507,7 +511,6 @@ function(ImageWrapper, CVUtils, Rasterizer, Tracer, skeletonizer, ArrayHelper, I
|
|||||||
}
|
}
|
||||||
|
|
||||||
boxes = findBoxes(topLabels, maxLabel);
|
boxes = findBoxes(topLabels, maxLabel);
|
||||||
|
|
||||||
return boxes;
|
return boxes;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
+5
-2
@@ -11,19 +11,22 @@ define(function(){
|
|||||||
debug: false,
|
debug: false,
|
||||||
controls: false,
|
controls: false,
|
||||||
locate: true,
|
locate: true,
|
||||||
|
numOfWorkers: 4,
|
||||||
|
scriptName: 'quagga.js',
|
||||||
visual: {
|
visual: {
|
||||||
show: true
|
show: true
|
||||||
},
|
},
|
||||||
decoder:{
|
decoder:{
|
||||||
drawBoundingBox: true,
|
drawBoundingBox: false,
|
||||||
showFrequency: false,
|
showFrequency: false,
|
||||||
drawScanline: true,
|
drawScanline: false,
|
||||||
showPattern: false,
|
showPattern: false,
|
||||||
readers: [
|
readers: [
|
||||||
'code_128_reader'
|
'code_128_reader'
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
locator: {
|
locator: {
|
||||||
|
halfSample: true,
|
||||||
showCanvas: false,
|
showCanvas: false,
|
||||||
showPatches: false,
|
showPatches: false,
|
||||||
showFoundPatches: false,
|
showFoundPatches: false,
|
||||||
|
|||||||
+2
-2
@@ -23,10 +23,10 @@ define(function() {
|
|||||||
function publishSubscription(subscription, data) {
|
function publishSubscription(subscription, data) {
|
||||||
if (subscription.async) {
|
if (subscription.async) {
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
subscription.callback.call(null, data);
|
subscription.callback(data);
|
||||||
}, 4);
|
}, 4);
|
||||||
} else {
|
} else {
|
||||||
subscription.callback.call(null, data);
|
subscription.callback(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+212
-53
@@ -1,8 +1,8 @@
|
|||||||
/* jshint undef: true, unused: true, browser:true, devel: true */
|
/* jshint undef: true, unused: true, browser:true, devel: true */
|
||||||
/* global define, vec2 */
|
/* global define, vec2, importScripts */
|
||||||
|
|
||||||
define(["code_128_reader", "ean_reader", "input_stream", "image_wrapper", "barcode_locator", "barcode_decoder", "frame_grabber", "html_utils", "config", "events", "camera_access"],
|
define(["code_128_reader", "ean_reader", "input_stream", "image_wrapper", "barcode_locator", "barcode_decoder", "frame_grabber", "html_utils", "config", "events", "camera_access", "async", "image_debug"],
|
||||||
function(Code128Reader, EANReader, InputStream, ImageWrapper, BarcodeLocator, BarcodeDecoder, FrameGrabber, HtmlUtils, _config, Events, CameraAccess) {
|
function(Code128Reader, EANReader, InputStream, ImageWrapper, BarcodeLocator, BarcodeDecoder, FrameGrabber, HtmlUtils, _config, Events, CameraAccess, async, ImageDebug) {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var _inputStream,
|
var _inputStream,
|
||||||
@@ -21,11 +21,12 @@ function(Code128Reader, EANReader, InputStream, ImageWrapper, BarcodeLocator, Ba
|
|||||||
_inputImageWrapper,
|
_inputImageWrapper,
|
||||||
_boxSize,
|
_boxSize,
|
||||||
_decoder,
|
_decoder,
|
||||||
_initialized = false;
|
_workerPool = [],
|
||||||
|
_onUIThread = true;
|
||||||
|
|
||||||
function initialize(config) {
|
function initializeData(imageWrapper) {
|
||||||
_config = HtmlUtils.mergeObjects(_config, config);
|
initBuffers(imageWrapper);
|
||||||
initInputStream();
|
_decoder = BarcodeDecoder.create(_config.decoder, _inputImageWrapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
function initConfig() {
|
function initConfig() {
|
||||||
@@ -48,7 +49,7 @@ function(Code128Reader, EANReader, InputStream, ImageWrapper, BarcodeLocator, Ba
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function initInputStream() {
|
function initInputStream(cb) {
|
||||||
var video;
|
var video;
|
||||||
if (_config.inputStream.type == "VideoStream") {
|
if (_config.inputStream.type == "VideoStream") {
|
||||||
video = document.createElement("video");
|
video = document.createElement("video");
|
||||||
@@ -74,24 +75,30 @@ function(Code128Reader, EANReader, InputStream, ImageWrapper, BarcodeLocator, Ba
|
|||||||
_inputStream.setAttribute("preload", "auto");
|
_inputStream.setAttribute("preload", "auto");
|
||||||
_inputStream.setAttribute("autoplay", true);
|
_inputStream.setAttribute("autoplay", true);
|
||||||
_inputStream.setInputStream(_config.inputStream);
|
_inputStream.setInputStream(_config.inputStream);
|
||||||
_inputStream.addEventListener("canrecord", canRecord);
|
_inputStream.addEventListener("canrecord", canRecord.bind(undefined, cb));
|
||||||
}
|
}
|
||||||
|
|
||||||
function canRecord() {
|
function canRecord(cb) {
|
||||||
initBuffers();
|
|
||||||
initCanvas();
|
initCanvas();
|
||||||
_decoder = BarcodeDecoder.create(_config.decoder, _inputImageWrapper);
|
|
||||||
_framegrabber = FrameGrabber.create(_inputStream, _canvasContainer.dom.image);
|
_framegrabber = FrameGrabber.create(_inputStream, _canvasContainer.dom.image);
|
||||||
_framegrabber.attachData(_inputImageWrapper.data);
|
|
||||||
|
|
||||||
initConfig();
|
initConfig();
|
||||||
_inputStream.play();
|
|
||||||
_initialized = true;
|
if (_config.numOfWorkers > 0) {
|
||||||
if (_config.readyFunc) {
|
initWorkers(function() {
|
||||||
_config.readyFunc.apply();
|
console.log("Workers created");
|
||||||
|
ready(cb);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
initializeData();
|
||||||
|
ready(cb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function ready(cb){
|
||||||
|
_inputStream.play();
|
||||||
|
cb();
|
||||||
|
}
|
||||||
|
|
||||||
function initCanvas() {
|
function initCanvas() {
|
||||||
var $viewport = document.querySelector("#interactive.viewport");
|
var $viewport = document.querySelector("#interactive.viewport");
|
||||||
_canvasContainer.dom.image = document.querySelector("canvas.imgBuffer");
|
_canvasContainer.dom.image = document.querySelector("canvas.imgBuffer");
|
||||||
@@ -103,8 +110,8 @@ function(Code128Reader, EANReader, InputStream, ImageWrapper, BarcodeLocator, Ba
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
_canvasContainer.ctx.image = _canvasContainer.dom.image.getContext("2d");
|
_canvasContainer.ctx.image = _canvasContainer.dom.image.getContext("2d");
|
||||||
_canvasContainer.dom.image.width = _inputImageWrapper.size.x;
|
_canvasContainer.dom.image.width = _inputStream.getWidth();
|
||||||
_canvasContainer.dom.image.height = _inputImageWrapper.size.y;
|
_canvasContainer.dom.image.height = _inputStream.getHeight();
|
||||||
|
|
||||||
_canvasContainer.dom.overlay = document.querySelector("canvas.drawingBuffer");
|
_canvasContainer.dom.overlay = document.querySelector("canvas.drawingBuffer");
|
||||||
if (!_canvasContainer.dom.overlay) {
|
if (!_canvasContainer.dom.overlay) {
|
||||||
@@ -120,52 +127,86 @@ function(Code128Reader, EANReader, InputStream, ImageWrapper, BarcodeLocator, Ba
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
_canvasContainer.ctx.overlay = _canvasContainer.dom.overlay.getContext("2d");
|
_canvasContainer.ctx.overlay = _canvasContainer.dom.overlay.getContext("2d");
|
||||||
_canvasContainer.dom.overlay.width = _inputImageWrapper.size.x;
|
_canvasContainer.dom.overlay.width = _inputStream.getWidth();
|
||||||
_canvasContainer.dom.overlay.height = _inputImageWrapper.size.y;
|
_canvasContainer.dom.overlay.height = _inputStream.getHeight();
|
||||||
}
|
}
|
||||||
|
|
||||||
function initBuffers() {
|
function initBuffers(imageWrapper) {
|
||||||
|
if (imageWrapper) {
|
||||||
|
_inputImageWrapper = imageWrapper;
|
||||||
|
} else {
|
||||||
_inputImageWrapper = new ImageWrapper({
|
_inputImageWrapper = new ImageWrapper({
|
||||||
x : _inputStream.getWidth(),
|
x : _inputStream.getWidth(),
|
||||||
y : _inputStream.getHeight()
|
y : _inputStream.getHeight()
|
||||||
});
|
});
|
||||||
console.log(_inputStream.getWidth());
|
}
|
||||||
console.log(_inputStream.getHeight());
|
|
||||||
|
console.log(_inputImageWrapper.size);
|
||||||
_boxSize = [
|
_boxSize = [
|
||||||
vec2.create([20, _inputStream.getHeight() / 2 - 100]),
|
vec2.create([20, _inputImageWrapper.size.y / 2 - 100]),
|
||||||
vec2.create([20, _inputStream.getHeight() / 2 + 100]),
|
vec2.create([20, _inputImageWrapper.size.y / 2 + 100]),
|
||||||
vec2.create([_inputStream.getWidth() - 20, _inputStream.getHeight() / 2 + 100]),
|
vec2.create([_inputImageWrapper.size.x - 20, _inputImageWrapper.size.y / 2 + 100]),
|
||||||
vec2.create([_inputStream.getWidth() - 20, _inputStream.getHeight() / 2 - 100])
|
vec2.create([_inputImageWrapper.size.x - 20, _inputImageWrapper.size.y / 2 - 100])
|
||||||
];
|
];
|
||||||
BarcodeLocator.init(_config.locator, {
|
BarcodeLocator.init(_inputImageWrapper, _config.locator);
|
||||||
inputImageWrapper : _inputImageWrapper
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getBoundingBoxes() {
|
function getBoundingBoxes() {
|
||||||
var boxes;
|
|
||||||
|
|
||||||
if (_config.locate) {
|
if (_config.locate) {
|
||||||
boxes = BarcodeLocator.locate();
|
return BarcodeLocator.locate();
|
||||||
} else {
|
} else {
|
||||||
boxes = [_boxSize];
|
return [_boxSize];
|
||||||
}
|
}
|
||||||
return boxes;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function update() {
|
function locateAndDecode() {
|
||||||
var result,
|
var result,
|
||||||
boxes;
|
boxes;
|
||||||
|
|
||||||
if (_framegrabber.grab()) {
|
|
||||||
_canvasContainer.ctx.overlay.clearRect(0, 0, _inputImageWrapper.size.x, _inputImageWrapper.size.y);
|
|
||||||
boxes = getBoundingBoxes();
|
boxes = getBoundingBoxes();
|
||||||
if (boxes) {
|
if (boxes) {
|
||||||
result = _decoder.decodeFromBoundingBoxes(boxes);
|
result = _decoder.decodeFromBoundingBoxes(boxes);
|
||||||
|
result = result || {};
|
||||||
|
result.boxes = boxes;
|
||||||
|
Events.publish("processed", result);
|
||||||
if (result && result.codeResult) {
|
if (result && result.codeResult) {
|
||||||
Events.publish("detected", result.codeResult.code);
|
Events.publish("detected", result);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Events.publish("processed");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function update() {
|
||||||
|
var availableWorker;
|
||||||
|
|
||||||
|
if (_onUIThread) {
|
||||||
|
if (_workerPool.length > 0) {
|
||||||
|
availableWorker = _workerPool.filter(function(workerThread) {
|
||||||
|
return !workerThread.busy;
|
||||||
|
})[0];
|
||||||
|
if (availableWorker) {
|
||||||
|
_framegrabber.attachData(availableWorker.imageData);
|
||||||
|
} else {
|
||||||
|
return; // all workers are busy
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_framegrabber.attachData(_inputImageWrapper.data);
|
||||||
|
}
|
||||||
|
if (_framegrabber.grab()) {
|
||||||
|
if (availableWorker) {
|
||||||
|
availableWorker.busy = true;
|
||||||
|
availableWorker.worker.postMessage({
|
||||||
|
cmd: 'process',
|
||||||
|
imageData: availableWorker.imageData
|
||||||
|
}, [availableWorker.imageData.buffer]);
|
||||||
|
} else {
|
||||||
|
locateAndDecode();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
locateAndDecode();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,20 +214,136 @@ function(Code128Reader, EANReader, InputStream, ImageWrapper, BarcodeLocator, Ba
|
|||||||
_stopped = false;
|
_stopped = false;
|
||||||
( function frame() {
|
( function frame() {
|
||||||
if (!_stopped) {
|
if (!_stopped) {
|
||||||
if (_config.inputStream.type == "LiveStream") {
|
update();
|
||||||
|
if (_onUIThread && _config.inputStream.type == "LiveStream") {
|
||||||
window.requestAnimFrame(frame);
|
window.requestAnimFrame(frame);
|
||||||
}
|
}
|
||||||
update();
|
|
||||||
}
|
}
|
||||||
}());
|
}());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function initWorkers(cb) {
|
||||||
|
_workerPool = [];
|
||||||
|
|
||||||
|
async.times(_config.numOfWorkers, function(n, next) {
|
||||||
|
initWorker(function(workerThread) {
|
||||||
|
_workerPool.push(workerThread);
|
||||||
|
next(null);
|
||||||
|
});
|
||||||
|
}, cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
function initWorker(cb) {
|
||||||
|
var blobURL,
|
||||||
|
workerThread = {
|
||||||
|
worker: null,
|
||||||
|
imageData: new Uint8Array(_inputStream.getWidth() * _inputStream.getHeight()),
|
||||||
|
busy: true
|
||||||
|
};
|
||||||
|
|
||||||
|
blobURL = generateWorkerBlob();
|
||||||
|
workerThread.worker = new Worker(blobURL);
|
||||||
|
URL.revokeObjectURL(blobURL);
|
||||||
|
|
||||||
|
workerThread.worker.onmessage = function(e) {
|
||||||
|
if (e.data.event === 'initialized') {
|
||||||
|
workerThread.busy = false;
|
||||||
|
workerThread.imageData = new Uint8Array(e.data.imageData);
|
||||||
|
console.log("Worker initialized");
|
||||||
|
return cb(workerThread);
|
||||||
|
} else if (e.data.event === 'processed') {
|
||||||
|
workerThread.imageData = new Uint8Array(e.data.imageData);
|
||||||
|
workerThread.busy = false;
|
||||||
|
Events.publish("processed", e.data.result);
|
||||||
|
if (e.data.result && e.data.result.codeResult) {
|
||||||
|
Events.publish("detected", e.data.result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
workerThread.worker.postMessage({
|
||||||
|
cmd: 'init',
|
||||||
|
size: {x: _inputStream.getWidth(), y: _inputStream.getHeight()},
|
||||||
|
imageData: workerThread.imageData,
|
||||||
|
config: _config
|
||||||
|
}, [workerThread.imageData.buffer]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function workerInterface(scriptUrl) {
|
||||||
|
importScripts(scriptUrl);
|
||||||
|
/* jshint ignore:start */
|
||||||
|
var imageWrapper;
|
||||||
|
|
||||||
|
self.onmessage = function(e) {
|
||||||
|
if (e.data.cmd === 'init') {
|
||||||
|
var config = e.data.config;
|
||||||
|
config.numOfWorkers = 0;
|
||||||
|
imageWrapper = new Quagga.ImageWrapper({
|
||||||
|
x : e.data.size.x,
|
||||||
|
y : e.data.size.y
|
||||||
|
}, new Uint8Array(e.data.imageData));
|
||||||
|
Quagga.init(config, ready, imageWrapper);
|
||||||
|
Quagga.onProcessed(onProcessed);
|
||||||
|
} else if (e.data.cmd === 'process') {
|
||||||
|
imageWrapper.data = new Uint8Array(e.data.imageData);
|
||||||
|
Quagga.start();
|
||||||
|
} else if (e.data.cmd === 'setReaders') {
|
||||||
|
Quagga.setReaders(e.data.readers);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function onProcessed(result) {
|
||||||
|
self.postMessage({'event': 'processed', imageData: imageWrapper.data, result: result}, [imageWrapper.data.buffer]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function ready() {
|
||||||
|
self.postMessage({'event': 'initialized', imageData: imageWrapper.data}, [imageWrapper.data.buffer]);
|
||||||
|
}
|
||||||
|
/* jshint ignore:end */
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateWorkerBlob() {
|
||||||
|
var blob,
|
||||||
|
quaggaAbsoluteUrl,
|
||||||
|
scripts = document.getElementsByTagName('script'),
|
||||||
|
regex = new RegExp('\/' + _config.scriptName + '$');
|
||||||
|
|
||||||
|
quaggaAbsoluteUrl = Array.prototype.slice.apply(scripts).filter(function(script) {
|
||||||
|
return script.src && script.src.match(regex);
|
||||||
|
}).map(function(script) {
|
||||||
|
return script.src;
|
||||||
|
})[0];
|
||||||
|
|
||||||
|
|
||||||
|
blob = new Blob(['(' + workerInterface.toString() + ')("' + quaggaAbsoluteUrl + '");'],
|
||||||
|
{type : 'text/javascript'});
|
||||||
|
|
||||||
|
return window.URL.createObjectURL(blob);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setReaders(readers) {
|
||||||
|
if (_decoder) {
|
||||||
|
_decoder.setReaders(readers);
|
||||||
|
} else if (_onUIThread && _workerPool.length > 0) {
|
||||||
|
_workerPool.forEach(function(workerThread) {
|
||||||
|
workerThread.worker.postMessage({cmd: 'setReaders', readers: readers});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
init : function(config) {
|
init : function(config, cb, imageWrapper) {
|
||||||
initialize(config);
|
_config = HtmlUtils.mergeObjects(_config, config);
|
||||||
|
if (imageWrapper) {
|
||||||
|
_onUIThread = false;
|
||||||
|
initializeData(imageWrapper);
|
||||||
|
return cb();
|
||||||
|
} else {
|
||||||
|
initInputStream(cb);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
start : function() {
|
start : function() {
|
||||||
console.log("Start!");
|
|
||||||
start();
|
start();
|
||||||
},
|
},
|
||||||
stop : function() {
|
stop : function() {
|
||||||
@@ -198,11 +355,11 @@ function(Code128Reader, EANReader, InputStream, ImageWrapper, BarcodeLocator, Ba
|
|||||||
onDetected : function(callback) {
|
onDetected : function(callback) {
|
||||||
Events.subscribe("detected", callback);
|
Events.subscribe("detected", callback);
|
||||||
},
|
},
|
||||||
isInitialized : function() {
|
onProcessed: function(callback) {
|
||||||
return _initialized;
|
Events.subscribe("processed", callback);
|
||||||
},
|
},
|
||||||
setReaders: function(readers) {
|
setReaders: function(readers) {
|
||||||
_decoder.setReaders(readers);
|
setReaders(readers);
|
||||||
},
|
},
|
||||||
canvas : _canvasContainer,
|
canvas : _canvasContainer,
|
||||||
decodeSingle : function(config, resultCallback) {
|
decodeSingle : function(config, resultCallback) {
|
||||||
@@ -212,18 +369,20 @@ function(Code128Reader, EANReader, InputStream, ImageWrapper, BarcodeLocator, Ba
|
|||||||
sequence : false,
|
sequence : false,
|
||||||
size: 800
|
size: 800
|
||||||
};
|
};
|
||||||
config.readyFunc = function() {
|
config.numOfWorkers = 1;
|
||||||
|
this.init(config, function() {
|
||||||
Events.once("detected", function(result) {
|
Events.once("detected", function(result) {
|
||||||
_stopped = true;
|
_stopped = true;
|
||||||
resultCallback.call(null, result);
|
resultCallback.call(null, result);
|
||||||
}, true);
|
}, true);
|
||||||
start();
|
start();
|
||||||
};
|
});
|
||||||
initialize(config);
|
|
||||||
},
|
},
|
||||||
Reader: {
|
Reader: {
|
||||||
EANReader : EANReader,
|
EANReader : EANReader,
|
||||||
Code128Reader : Code128Reader
|
Code128Reader : Code128Reader
|
||||||
}
|
},
|
||||||
|
ImageWrapper: ImageWrapper,
|
||||||
|
ImageDebug: ImageDebug
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|||||||
+8
-8
@@ -4,18 +4,18 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
glMatrixArrayType = Float32Array;
|
glMatrixArrayType = Float32Array;
|
||||||
|
if (typeof window !== 'undefined') {
|
||||||
window.requestAnimFrame = (function() {
|
window.requestAnimFrame = (function () {
|
||||||
return window.requestAnimationFrame ||
|
return window.requestAnimationFrame ||
|
||||||
window.webkitRequestAnimationFrame ||
|
window.webkitRequestAnimationFrame ||
|
||||||
window.mozRequestAnimationFrame ||
|
window.mozRequestAnimationFrame ||
|
||||||
window.oRequestAnimationFrame ||
|
window.oRequestAnimationFrame ||
|
||||||
window.msRequestAnimationFrame ||
|
window.msRequestAnimationFrame ||
|
||||||
function(/* function FrameRequestCallback */ callback, /* DOMElement Element */ element) {
|
function (/* function FrameRequestCallback */ callback, /* DOMElement Element */ element) {
|
||||||
window.setTimeout(callback, 1000/60);
|
window.setTimeout(callback, 1000 / 60);
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
|
||||||
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
|
window.URL = window.URL || window.webkitURL || window.mozURL || window.msURL;
|
||||||
window.URL = window.URL || window.webkitURL || window.mozURL || window.msURL;
|
}
|
||||||
|
|||||||
Vendored
+1123
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user