Skip to content

Commit a852394

Browse files
committed
Merge pull request #65 from serratus/issue-38
closes #38 by adding node support
2 parents e5acf19 + b340883 commit a852394

25 files changed

+530
-35063
lines changed

Gruntfile.js

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -45,21 +45,12 @@ module.exports = function(grunt) {
4545
"typedefs" : {
4646
"deps" : [],
4747
"exports" : "typedefs"
48-
},
49-
"glMatrix" : {
50-
"deps" : ["typedefs"],
51-
"exports" : "glMatrix"
52-
},
53-
"glMatrixAddon" : {
54-
"deps" : ["glMatrix"],
55-
"exports" : "glMatrixAddon"
5648
}
5749
},
5850

5951
"paths" : {
6052
"typedefs" : "typedefs",
61-
"glMatrix" : "vendor/glMatrix",
62-
"glMatrixAddon" : "glMatrixAddon"
53+
"gl-matrix": "../node_modules/gl-matrix/dist/gl-matrix-min"
6354
}
6455
}
6556
}

README.md

Lines changed: 68 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
quaggaJS
22
========
33

4-
- [Changelog](#changelog) (2015-08-29)
4+
- [Changelog](#changelog) (2015-09-15)
55

66
## What is QuaggaJS?
77

@@ -43,12 +43,12 @@ In cases where real-time decoding is not needed, or the platform does not
4343
support `getUserMedia` QuaggaJS is also capable of decoding image-files using
4444
the File API or other URL sources.
4545

46-
## Getting Started
46+
## Installing
4747

48-
You can simply include `dist/quagga.min.js` in your project and you are ready
49-
to go.
48+
QuaggaJS can be installed using __npm__, __bower__, or by including it with
49+
the __script__ tag.
5050

51-
If you want to keep your project modular, you can also install QuaggaJS via npm:
51+
### NPM
5252

5353
```console
5454
> npm install quagga
@@ -57,12 +57,33 @@ If you want to keep your project modular, you can also install QuaggaJS via npm:
5757
And then import it as dependency in your project:
5858

5959
```javascript
60-
var quagga = require('quagga');
60+
var Quagga = require('quagga');
61+
```
62+
63+
Currently, the full functionality is only available through the browser. When
64+
using QuaggaJS within __node__, only file-based decoding is available. See the
65+
example for [node_examples](#node-example).
66+
67+
### Bower
68+
69+
You can also install QuaggaJS through __bower__:
70+
71+
```console
72+
> bower install quagga
6173
```
6274

75+
### Script-Tag Anno 1998
76+
77+
You can simply include `dist/quagga.min.js` in your project and you are ready
78+
to go.
79+
80+
81+
## Getting Started
82+
6383
For starters, have a look at the [examples][github_examples] to get an idea
6484
where to go from here.
6585

86+
6687
## <a name="Building">Building</a>
6788

6889
You can build the library yourself by simply cloning the repo and typing:
@@ -295,7 +316,39 @@ Quagga.decodeSingle({
295316
locate: true, // try to locate the barcode in the image
296317
src: '/test/fixtures/code_128/image-001.jpg' // or 'data:image/jpg;base64,' + data
297318
}, function(result){
298-
console.log(result);
319+
if(result.codeResult) {
320+
console.log("result", result.codeResult.code);
321+
} else {
322+
console.log("not detected");
323+
}
324+
});
325+
```
326+
327+
### <a name="node-example">Using node</a>
328+
329+
The following example illustrates the use of QuaggaJS within a node
330+
environment. It's almost identical to the browser version with the difference
331+
that node does not support web-workers out of the box. Therefore the config
332+
property `numOfWorkers` must be explicitly set to `0`.
333+
334+
```javascript
335+
var Quagga = require('quagga');
336+
337+
Quagga.decodeSingle({
338+
src: "image-abc-123.jpg",
339+
numOfWorkers: 0, // Needs to be 0 when used within node
340+
inputStream: {
341+
size: 800 // restrict input-size to be 800px in width (long-side)
342+
},
343+
decoder: {
344+
readers: ["code_128_reader"] // List of active readers
345+
},
346+
}, function(result) {
347+
if(result.codeResult) {
348+
console.log("result", result.codeResult.code);
349+
} else {
350+
console.log("not detected");
351+
}
299352
});
300353
```
301354

@@ -377,6 +430,14 @@ on the ``singleChannel`` flag in the configuration when using ``decodeSingle``.
377430

378431
## <a name="changelog">Changelog</a>
379432

433+
### 2015-09-15
434+
Take a look at the release-notes ([0.7.0]
435+
(https://github.com/serratus/quaggaJS/releases/tag/v0.7.0))
436+
437+
- Features
438+
- Added basic support for running QuaggaJS inside __node__ (see [example]
439+
(#node-example))
440+
380441
### 2015-08-29
381442
- Improvements
382443
- Added support for Internet Explorer (only Edge+ supports `getUserMedia`)

dist/quagga.js

Lines changed: 77 additions & 2313 deletions
Large diffs are not rendered by default.

dist/quagga.min.js

Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

example/file_input_require.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,6 @@ <h3>Working with file-input</h3>
9696
</p>
9797
</footer>
9898
<script src="../src/vendor/jquery-1.9.0.min.js" type="text/javascript"></script>
99-
<script data-main="file_input_require.js" src="../src/vendor/require.js"></script>
99+
<script data-main="file_input_require.js" src="../node_modules/requirejs/require.js"></script>
100100
</body>
101101
</html>

example/file_input_require.js

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,25 +4,16 @@ requirejs.config({
44
"typedefs" : {
55
"deps" : [],
66
"exports" : "typedefs"
7-
},
8-
"glMatrix" : {
9-
"deps" : ["typedefs"],
10-
"exports" : "glMatrix"
11-
},
12-
"glMatrixAddon" : {
13-
"deps" : ["glMatrix"],
14-
"exports" : "glMatrixAddon"
157
}
168
},
179

1810
"paths" : {
1911
"typedefs" : "typedefs",
20-
"glMatrix" : "vendor/glMatrix",
21-
"glMatrixAddon" : "glMatrixAddon"
12+
"gl-matrix": "../node_modules/gl-matrix/dist/gl-matrix-min"
2213
}
2314
});
2415

25-
define(['quagga'], function(Quagga) {
16+
requirejs(['quagga'], function(Quagga) {
2617
var App = {
2718
init: function() {
2819
App.attachListeners();
@@ -116,13 +107,13 @@ define(['quagga'], function(Quagga) {
116107
singleChannel: false
117108
},
118109
locator: {
119-
patchSize: "large",
110+
patchSize: "medium",
120111
halfSample: true,
121112
showCanvas: true
122113
},
123114
numOfWorkers: 0,
124115
decoder: {
125-
readers: ["i2of5_reader"],
116+
readers: ["code_128_reader"],
126117
showFrequency: true,
127118
showPattern: true
128119
},

example/node-test.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
var Quagga = require('../lib/quagga');
2+
3+
Quagga.decodeSingle({
4+
src: "../test/fixtures/code_128/image-001.jpg",
5+
numOfWorkers: 0,
6+
inputStream: {
7+
size: 800,
8+
area: {
9+
top: "10%",
10+
right: "5%",
11+
left: "5%",
12+
bottom: "10%"
13+
}
14+
}
15+
}, function(result) {
16+
if(result.codeResult) {
17+
console.log("result", result.codeResult.code);
18+
} else {
19+
console.log("not detected");
20+
}
21+
});

karma-integration.conf.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ module.exports = function(config) {
44
frameworks: ['mocha', 'requirejs', 'chai', 'sinon', 'sinon-chai'],
55
files: [
66
'test-main.js',
7-
'src/vendor/glMatrix.js',
87
'src/typedefs.js',
98
{pattern: 'node_modules/async/lib/async.js', included: false},
9+
{pattern: 'node_modules/gl-matrix/dist/gl-matrix-min.js', included: false},
1010
{pattern: 'src/*.js', included: false},
1111
{pattern: 'spec/**/*integration.spec.js', included: false},
1212
{pattern: 'test/**/*.*', included: false}

karma.conf.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ module.exports = function(config) {
44
frameworks: ['mocha', 'requirejs', 'chai', 'sinon', 'sinon-chai'],
55
files: [
66
'test-main.js',
7-
'src/vendor/glMatrix.js',
87
'src/typedefs.js',
98
{pattern: 'node_modules/async/lib/async.js', included: false},
9+
{pattern: 'node_modules/gl-matrix/dist/gl-matrix-min.js', included: false},
1010
{pattern: 'src/*.js', included: false},
1111
{pattern: 'spec/**/*.js', included: false},
1212
{pattern: 'test/**/*.*', included: false}

lib/frame_grabber.js

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/* jshint undef: true, unused: true, browser:true, devel: true */
2+
/* global define */
3+
4+
define(["cv_utils"], function(CVUtils) {
5+
"use strict";
6+
7+
var Ndarray = require("ndarray"),
8+
Interp2D = require("ndarray-linear-interpolate").d2;
9+
10+
var FrameGrabber = {};
11+
12+
FrameGrabber.create = function(inputStream) {
13+
var _that = {},
14+
_streamConfig = inputStream.getConfig(),
15+
_video_size = CVUtils.imageRef(inputStream.getRealWidth(), inputStream.getRealHeight()),
16+
_canvasSize = inputStream.getCanvasSize(),
17+
_size = CVUtils.imageRef(inputStream.getWidth(), inputStream.getHeight()),
18+
_topRight = inputStream.getTopRight(),
19+
_data = new Uint8Array(_size.x * _size.y),
20+
_grayData = new Uint8Array(_video_size.x * _video_size.y),
21+
_canvasData = new Uint8Array(_canvasSize.x * _canvasSize.y),
22+
_grayImageArray = Ndarray(_grayData, [_video_size.y, _video_size.x]).transpose(1, 0),
23+
_canvasImageArray = Ndarray(_canvasData, [_canvasSize.y, _canvasSize.x]).transpose(1, 0),
24+
_targetImageArray = _canvasImageArray.hi(_topRight.x + _size.x, _topRight.y + _size.y).lo(_topRight.x, _topRight.y),
25+
_stepSizeX = _video_size.x/_canvasSize.x,
26+
_stepSizeY = _video_size.y/_canvasSize.y;
27+
28+
console.log("FrameGrabber", JSON.stringify({
29+
videoSize: _grayImageArray.shape,
30+
canvasSize: _canvasImageArray.shape,
31+
stepSize: [_stepSizeX, _stepSizeY],
32+
size: _targetImageArray.shape,
33+
topRight: _topRight
34+
}));
35+
36+
/**
37+
* Uses the given array as frame-buffer
38+
*/
39+
_that.attachData = function(data) {
40+
_data = data;
41+
};
42+
43+
/**
44+
* Returns the used frame-buffer
45+
*/
46+
_that.getData = function() {
47+
return _data;
48+
};
49+
50+
/**
51+
* Fetches a frame from the input-stream and puts into the frame-buffer.
52+
* The image-data is converted to gray-scale and then half-sampled if configured.
53+
*/
54+
_that.grab = function() {
55+
var frame = inputStream.getFrame();
56+
57+
if (frame) {
58+
this.scaleAndCrop(frame);
59+
return true;
60+
} else {
61+
return false;
62+
}
63+
};
64+
65+
_that.scaleAndCrop = function(frame) {
66+
var x,
67+
y;
68+
69+
// 1. compute full-sized gray image
70+
CVUtils.computeGray(frame.data, _grayData);
71+
72+
// 2. interpolate
73+
for (y = 0; y < _canvasSize.y; y++) {
74+
for (x = 0; x < _canvasSize.x; x++) {
75+
_canvasImageArray.set(x, y, (Interp2D(_grayImageArray, x * _stepSizeX, y * _stepSizeY)) | 0);
76+
}
77+
}
78+
79+
// targetImageArray must be equal to targetSize
80+
if (_targetImageArray.shape[0] !== _size.x ||
81+
_targetImageArray.shape[1] !== _size.y) {
82+
throw new Error("Shapes do not match!");
83+
}
84+
85+
// 3. crop
86+
for (y = 0; y < _size.y; y++) {
87+
for (x = 0; x < _size.x; x++) {
88+
_data[y * _size.x + x] = _targetImageArray.get(x, y);
89+
}
90+
}
91+
},
92+
93+
_that.getSize = function() {
94+
return _size;
95+
};
96+
97+
return _that;
98+
};
99+
100+
return (FrameGrabber);
101+
});

0 commit comments

Comments
 (0)