mirror of
https://github.com/serratus/quaggaJS.git
synced 2026-08-13 05:31:37 +08:00
Merge branch 'master' of https://github.com/serratus/quaggaJS into jclarkin-master
This commit is contained in:
@@ -34,6 +34,7 @@ module.exports = function(grunt) {
|
||||
},
|
||||
"baseUrl" : "src",
|
||||
"name" : "quagga",
|
||||
"useStrict": true,
|
||||
"out" : "dist/quagga.js",
|
||||
"include" : ['quagga'],
|
||||
"optimize" : "none",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
quaggaJS
|
||||
========
|
||||
|
||||
- [Changelog](#changelog) (2015-05-20)
|
||||
- [Changelog](#changelog) (2015-07-08)
|
||||
|
||||
## What is QuaggaJS?
|
||||
|
||||
@@ -80,12 +80,16 @@ version `quagga.min.js` and places both files in the `dist` folder.
|
||||
You can check out the [examples][github_examples] to get an idea of how to
|
||||
use QuaggaJS. Basically the library exposes the following API:
|
||||
|
||||
### Quagga.init(config, callback)
|
||||
### <a name="quaggainit">Quagga.init(config, callback)</a>
|
||||
|
||||
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.
|
||||
below) and invokes the `callback(err)` when Quagga has finished its
|
||||
bootstrapping phase. The initialization process also requests for camera
|
||||
access if real-time detection is configured. In case of an error, the `err`
|
||||
parameter is set and contains information about the cause. A potential cause
|
||||
may be the `inputStream.type` is set to `LiveStream`, but the browser does
|
||||
not support this API, or simply if the user denies the permission to use the
|
||||
camera.
|
||||
|
||||
```javascript
|
||||
Quagga.init({
|
||||
@@ -96,7 +100,11 @@ Quagga.init({
|
||||
decoder : {
|
||||
readers : ["code_128_reader"]
|
||||
}
|
||||
}, function() {
|
||||
}, function(err) {
|
||||
if (err) {
|
||||
console.log(err);
|
||||
return
|
||||
}
|
||||
console.log("Initialization finished. Ready to start");
|
||||
Quagga.start();
|
||||
});
|
||||
@@ -143,7 +151,8 @@ empty.
|
||||
```javascript
|
||||
{
|
||||
"codeResult": {
|
||||
"code": "FANAVF1461710",
|
||||
"code": "FANAVF1461710", // the decoded code as a string
|
||||
"format": "code_128", // or code_39, codabar, ean_13, ean_8, upc_a, upc_e
|
||||
"start": 355,
|
||||
"end": 26,
|
||||
"codeset": 100,
|
||||
@@ -212,12 +221,19 @@ The default `config` object is set as followed:
|
||||
```javascript
|
||||
{
|
||||
inputStream: { name: "Live",
|
||||
type: "LiveStream",
|
||||
constraints: {
|
||||
width: 640,
|
||||
height: 480,
|
||||
facing: "environment"
|
||||
}
|
||||
type: "LiveStream",
|
||||
constraints: {
|
||||
width: 640,
|
||||
height: 480,
|
||||
facing: "environment"
|
||||
},
|
||||
area: { // defines rectangle of the detection/localization area
|
||||
top: "0%", // top offset
|
||||
right: "0%", // right offset
|
||||
left: "0%", // left offset
|
||||
bottom: "0%" // bottom offset
|
||||
},
|
||||
singleChannel: false // true: only the red color-channel is read
|
||||
},
|
||||
tracking: false,
|
||||
debug: false,
|
||||
@@ -263,11 +279,13 @@ locating-mechanism for more robust results.
|
||||
|
||||
```javascript
|
||||
Quagga.decodeSingle({
|
||||
readers: ['code_128_reader'],
|
||||
locate: true, // try to locate the barcode in the image
|
||||
src: '/test/fixtures/code_128/image-001.jpg' // or 'data:image/jpg;base64,' + data
|
||||
decoder: {
|
||||
readers: ["code_128_reader"] // List of active readers
|
||||
},
|
||||
locate: true, // try to locate the barcode in the image
|
||||
src: '/test/fixtures/code_128/image-001.jpg' // or 'data:image/jpg;base64,' + data
|
||||
}, function(result){
|
||||
console.log(result);
|
||||
console.log(result);
|
||||
});
|
||||
```
|
||||
|
||||
@@ -291,8 +309,96 @@ 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="resultcollector">ResultCollector</a>
|
||||
|
||||
Quagga is not perfect by any means and may produce false positives from time
|
||||
to time. In order to find out which images produced those false positives,
|
||||
the built-in ``ResultCollector`` will support you and me helping squashing
|
||||
bugs in the implementation.
|
||||
|
||||
### Creating a ``ResultCollector``
|
||||
|
||||
You can easily create a new ``ResultCollector`` by calling its ``create``
|
||||
method with a configuration.
|
||||
|
||||
```javascript
|
||||
var resultCollector = Quagga.ResultCollector.create({
|
||||
capture: true, // keep track of the image producing this result
|
||||
capacity: 20, // maximum number of results to store
|
||||
blacklist: [ // list containing codes which should not be recorded
|
||||
{code: "3574660239843", format: "ean_13"}],
|
||||
filter: function(codeResult) {
|
||||
// only store results which match this constraint
|
||||
// returns true/false
|
||||
// e.g.: return codeResult.format === "ean_13";
|
||||
return true;
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### Using a ``ResultCollector``
|
||||
|
||||
After creating a ``ResultCollector`` you have to attach it to Quagga by
|
||||
calling ``Quagga.registerResultCollector(resultCollector)``.
|
||||
|
||||
### Reading results
|
||||
|
||||
After a test/recording session, you can now print the collected results which
|
||||
do not fit into a certain schema. Calling ``getResults`` on the
|
||||
``resultCollector`` returns an ``Array`` containing objects with:
|
||||
|
||||
```javascript
|
||||
{
|
||||
codeResult: {}, // same as in onDetected event
|
||||
frame: "data:image/png;base64,iVBOR..." // dataURL of the gray-scaled image
|
||||
}
|
||||
```
|
||||
|
||||
The ``frame`` property is an internal representation of the image and
|
||||
therefore only available in gray-scale. The dataURL representation allows
|
||||
easy saving/rendering of the image.
|
||||
|
||||
### Comparing results
|
||||
|
||||
Now, having the frames available on disk, you can load each single image by
|
||||
calling ``decodeSingle`` with the same configuration as used during recording
|
||||
. In order to reproduce the exact same result, you have to make sure to turn
|
||||
on the ``singleChannel`` flag in the configuration when using ``decodeSingle``.
|
||||
|
||||
## <a name="changelog">Changelog</a>
|
||||
|
||||
### 2015-07-08
|
||||
- Improvements
|
||||
- Parameter tweaking to reduce false-positives significantly (for the
|
||||
entire EAN and UPC family)
|
||||
- Fixing bug in parity check for UPC-E codes
|
||||
- Fixing bug in alignment for EAN-8 codes
|
||||
|
||||
### 2015-07-06
|
||||
- Improvements
|
||||
- Added `err` parameter to [Quagga.init()](#quaggainit) callback
|
||||
function
|
||||
|
||||
### 2015-06-21
|
||||
- Features
|
||||
- Added ``singleChannel`` configuration to ``inputStream`` (in [config]
|
||||
(#configobject))
|
||||
- Added ``ResultCollector`` functionality (see [ResultCollector]
|
||||
(#resultcollector))
|
||||
|
||||
### 2015-06-13
|
||||
- Improvements
|
||||
- Added ``format`` property to ``codeResult`` (in [result](#resultobject))
|
||||
|
||||
### 2015-06-13
|
||||
- Improvements
|
||||
- Added fixes for ``Code39Reader`` (trailing whitespace was missing)
|
||||
|
||||
### 2015-06-09
|
||||
- Features
|
||||
- Introduced the ``area`` property
|
||||
- Ability to define a rectangle where localization/decoding should be applied
|
||||
|
||||
### 2015-05-20
|
||||
- Improvements
|
||||
- Making EAN and UPC readers even more restrictive
|
||||
|
||||
Vendored
+536
-276
File diff suppressed because it is too large
Load Diff
Vendored
+4
-4
File diff suppressed because one or more lines are too long
@@ -74,7 +74,7 @@
|
||||
padding: 10px 0;
|
||||
}
|
||||
/* line 50, ../sass/_viewport.scss */
|
||||
#result_strip ul.thumbnails {
|
||||
#result_strip > ul {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
list-style-type: none;
|
||||
@@ -84,34 +84,34 @@
|
||||
white-space: nowrap;
|
||||
}
|
||||
/* line 59, ../sass/_viewport.scss */
|
||||
#result_strip ul.thumbnails > li {
|
||||
#result_strip > ul > li {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
width: 160px;
|
||||
}
|
||||
/* line 63, ../sass/_viewport.scss */
|
||||
#result_strip ul.thumbnails > li .thumbnail {
|
||||
#result_strip > ul > li .thumbnail {
|
||||
padding: 5px;
|
||||
margin: 4px;
|
||||
border: 1px dashed #CCC;
|
||||
}
|
||||
/* line 68, ../sass/_viewport.scss */
|
||||
#result_strip ul.thumbnails > li .thumbnail img {
|
||||
#result_strip > ul > li .thumbnail img {
|
||||
max-width: 140px;
|
||||
}
|
||||
/* line 71, ../sass/_viewport.scss */
|
||||
#result_strip ul.thumbnails > li .thumbnail .caption {
|
||||
#result_strip > ul > li .thumbnail .caption {
|
||||
white-space: normal;
|
||||
}
|
||||
/* line 73, ../sass/_viewport.scss */
|
||||
#result_strip ul.thumbnails > li .thumbnail .caption h4 {
|
||||
#result_strip > ul > li .thumbnail .caption h4 {
|
||||
text-align: center;
|
||||
word-wrap: break-word;
|
||||
height: 40px;
|
||||
margin: 0px;
|
||||
}
|
||||
/* line 83, ../sass/_viewport.scss */
|
||||
#result_strip ul.thumbnails:after {
|
||||
#result_strip > ul:after {
|
||||
content: "";
|
||||
display: table;
|
||||
clear: both;
|
||||
|
||||
@@ -77,14 +77,15 @@
|
||||
<span>Half-Sample</span>
|
||||
<input type="checkbox" name="locator_half-sample" />
|
||||
</label>
|
||||
<label>
|
||||
<span>Single Channel</span>
|
||||
<input type="checkbox" name="input-stream_single-channel" />
|
||||
</label>
|
||||
<label>
|
||||
<span>Workers</span>
|
||||
<select name="numOfWorkers">
|
||||
<option selected="selected" value="0">0</option>
|
||||
<option value="1">1</option>
|
||||
<option value="2">2</option>
|
||||
<option value="4">4</option>
|
||||
<option value="8">8</option>
|
||||
<option value="0">0</option>
|
||||
<option selected="selected" value="1">1</option>
|
||||
</select>
|
||||
</label>
|
||||
</fieldset>
|
||||
|
||||
+34
-7
@@ -88,17 +88,16 @@ $(function() {
|
||||
},
|
||||
state: {
|
||||
inputStream: {
|
||||
size: 640
|
||||
size: 640,
|
||||
singleChannel: false
|
||||
},
|
||||
locator: {
|
||||
patchSize: "large",
|
||||
halfSample: false
|
||||
},
|
||||
numOfWorkers: 0,
|
||||
numOfWorkers: 1,
|
||||
decoder: {
|
||||
readers: ["code_128_reader"],
|
||||
showFrequency: true,
|
||||
showPattern: true
|
||||
readers: ["code_128_reader"]
|
||||
},
|
||||
locate: true,
|
||||
src: null
|
||||
@@ -107,9 +106,31 @@ $(function() {
|
||||
|
||||
App.init();
|
||||
|
||||
function calculateRectFromArea(canvas, area) {
|
||||
var canvasWidth = canvas.width,
|
||||
canvasHeight = canvas.height,
|
||||
top = parseInt(area.top)/100,
|
||||
right = parseInt(area.right)/100,
|
||||
bottom = parseInt(area.bottom)/100,
|
||||
left = parseInt(area.left)/100;
|
||||
|
||||
top *= canvasHeight;
|
||||
right = canvasWidth - canvasWidth*right;
|
||||
bottom = canvasHeight - canvasHeight*bottom;
|
||||
left *= canvasWidth;
|
||||
|
||||
return {
|
||||
x: left,
|
||||
y: top,
|
||||
width: right - left,
|
||||
height: bottom - top
|
||||
};
|
||||
}
|
||||
|
||||
Quagga.onProcessed(function(result) {
|
||||
var drawingCtx = Quagga.canvas.ctx.overlay,
|
||||
drawingCanvas = Quagga.canvas.dom.overlay;
|
||||
drawingCanvas = Quagga.canvas.dom.overlay,
|
||||
area;
|
||||
|
||||
if (result) {
|
||||
if (result.boxes) {
|
||||
@@ -128,7 +149,13 @@ $(function() {
|
||||
if (result.codeResult && result.codeResult.code) {
|
||||
Quagga.ImageDebug.drawPath(result.line, {x: 'x', y: 'y'}, drawingCtx, {color: 'red', lineWidth: 3});
|
||||
}
|
||||
}
|
||||
|
||||
if (App.state.inputStream.area) {
|
||||
area = calculateRectFromArea(drawingCanvas, App.state.inputStream.area);
|
||||
drawingCtx.strokeStyle = "#0F0";
|
||||
drawingCtx.strokeRect(area.x, area.y, area.width, area.height);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Quagga.onDetected(function(result) {
|
||||
|
||||
@@ -68,24 +68,19 @@
|
||||
<select name="locator_patch-size">
|
||||
<option value="x-small">x-small</option>
|
||||
<option value="small">small</option>
|
||||
<option value="medium">medium</option>
|
||||
<option selected="selected" value="large">large</option>
|
||||
<option selected="selected" value="medium">medium</option>
|
||||
<option value="large">large</option>
|
||||
<option value="x-large">x-large</option>
|
||||
</select>
|
||||
</label>
|
||||
<label>
|
||||
<span>Half-Sample</span>
|
||||
<input type="checkbox" name="locator_half-sample" />
|
||||
<input type="checkbox" checked="checked"
|
||||
name="locator_half-sample" />
|
||||
</label>
|
||||
<label>
|
||||
<span>Workers</span>
|
||||
<select name="numOfWorkers">
|
||||
<option selected="selected" value="0">0</option>
|
||||
<option value="1">1</option>
|
||||
<option value="2">2</option>
|
||||
<option value="4">4</option>
|
||||
<option value="8">8</option>
|
||||
</select>
|
||||
<span>Single Channel</span>
|
||||
<input type="checkbox" name="input-stream_single-channel" />
|
||||
</label>
|
||||
</fieldset>
|
||||
</div>
|
||||
|
||||
@@ -112,11 +112,12 @@ define(['quagga'], function(Quagga) {
|
||||
},
|
||||
state: {
|
||||
inputStream: {
|
||||
size: 640
|
||||
size: 640,
|
||||
singleChannel: false
|
||||
},
|
||||
locator: {
|
||||
patchSize: "large",
|
||||
halfSample: false
|
||||
patchSize: "medium",
|
||||
halfSample: true
|
||||
},
|
||||
numOfWorkers: 0,
|
||||
decoder: {
|
||||
@@ -162,7 +163,7 @@ define(['quagga'], function(Quagga) {
|
||||
|
||||
$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("h4.code").html(code);
|
||||
$node.find("h4.code").html(code + " (" + result.codeResult.format + ")");
|
||||
$("#result_strip ul.thumbnails").prepend($node);
|
||||
});
|
||||
});
|
||||
@@ -82,6 +82,7 @@
|
||||
</div>
|
||||
<div id="result_strip">
|
||||
<ul class="thumbnails"></ul>
|
||||
<ul class="collector"></ul>
|
||||
</div>
|
||||
<div id="interactive" class="viewport"></div>
|
||||
</section>
|
||||
|
||||
@@ -1,17 +1,37 @@
|
||||
$(function() {
|
||||
var resultCollector = Quagga.ResultCollector.create({
|
||||
capture: true,
|
||||
capacity: 20,
|
||||
blacklist: [{code: "3574660239843", format: "ean_13"}],
|
||||
filter: function(codeResult) {
|
||||
// only store results which match this constraint
|
||||
// e.g.: codeResult
|
||||
return true;
|
||||
}
|
||||
});
|
||||
var App = {
|
||||
init : function() {
|
||||
Quagga.init(this.state, function() {
|
||||
var self = this;
|
||||
|
||||
Quagga.init(this.state, function(err) {
|
||||
if (err) {
|
||||
return self.handleError(err);
|
||||
}
|
||||
Quagga.registerResultCollector(resultCollector);
|
||||
App.attachListeners();
|
||||
Quagga.start();
|
||||
});
|
||||
},
|
||||
handleError: function(err) {
|
||||
console.log(err);
|
||||
},
|
||||
attachListeners: function() {
|
||||
var self = this;
|
||||
|
||||
$(".controls").on("click", "button.stop", function(e) {
|
||||
e.preventDefault();
|
||||
Quagga.stop();
|
||||
self._printCollectedResults();
|
||||
});
|
||||
|
||||
$(".controls .reader-config-group").on("change", "input, select", function(e) {
|
||||
@@ -25,6 +45,18 @@ $(function() {
|
||||
self.setState(state, value);
|
||||
});
|
||||
},
|
||||
_printCollectedResults: function() {
|
||||
var results = resultCollector.getResults(),
|
||||
$ul = $("#result_strip ul.collector");
|
||||
|
||||
results.forEach(function(result) {
|
||||
var $li = $('<li><div class="thumbnail"><div class="imgWrapper"><img /></div><div class="caption"><h4 class="code"></h4></div></div></li>');
|
||||
|
||||
$li.find("img").attr("src", result.frame);
|
||||
$li.find("h4.code").html(result.codeResult.code + " (" + result.codeResult.format + ")");
|
||||
$ul.prepend($li);
|
||||
});
|
||||
},
|
||||
_accessByPath: function(obj, path, val) {
|
||||
var parts = path.split('.'),
|
||||
depth = parts.length,
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
border-bottom: 1px solid #EEE;
|
||||
padding: 10px 0;
|
||||
|
||||
ul.thumbnails{
|
||||
& > ul {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
list-style-type: none;
|
||||
|
||||
+3
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "quagga",
|
||||
"version": "0.6.6",
|
||||
"version": "0.6.13",
|
||||
"description": "An advanced barcode-scanner written in JavaScript",
|
||||
"main": "dist/quagga.js",
|
||||
"devDependencies": {
|
||||
@@ -42,6 +42,8 @@
|
||||
"ean",
|
||||
"code128",
|
||||
"code39",
|
||||
"codabar",
|
||||
"upc",
|
||||
"getusermedia",
|
||||
"imageprocessing"
|
||||
],
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
|
||||
define(['barcode_locator', 'config', 'html_utils'],
|
||||
function(BarcodeLocator, Config, HtmlUtils){
|
||||
|
||||
describe('checkImageConstraints', function() {
|
||||
var config,
|
||||
inputStream,
|
||||
imageSize,
|
||||
streamConfig = {};
|
||||
|
||||
beforeEach(function() {
|
||||
imageSize = {
|
||||
x: 640, y: 480
|
||||
};
|
||||
config = HtmlUtils.mergeObjects({}, Config);
|
||||
inputStream = {
|
||||
getWidth: function() {
|
||||
return imageSize.x;
|
||||
},
|
||||
getHeight: function() {
|
||||
return imageSize.y;
|
||||
},
|
||||
setWidth: function() {},
|
||||
setHeight: function() {},
|
||||
setTopRight: function() {},
|
||||
setCanvasSize: function() {},
|
||||
getConfig: function() {
|
||||
return streamConfig;
|
||||
}
|
||||
};
|
||||
sinon.stub(inputStream, "setWidth", function(width) {
|
||||
imageSize.x = width;
|
||||
});
|
||||
sinon.stub(inputStream, "setHeight", function(height) {
|
||||
imageSize.y = height;
|
||||
});
|
||||
sinon.stub(inputStream, "setTopRight");
|
||||
sinon.stub(inputStream, "setCanvasSize");
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
inputStream.setWidth.restore();
|
||||
inputStream.setHeight.restore();
|
||||
});
|
||||
|
||||
it('should not adjust the image-size if not needed', function() {
|
||||
var expected = {x: imageSize.x, y: imageSize.y};
|
||||
BarcodeLocator.checkImageConstraints(inputStream, config.locator);
|
||||
expect(inputStream.getWidth()).to.be.equal(expected.x);
|
||||
expect(inputStream.getHeight()).to.be.equal(expected.y);
|
||||
});
|
||||
|
||||
it('should adjust the image-size', function() {
|
||||
var expected = {x: imageSize.x, y: imageSize.y};
|
||||
|
||||
config.locator.halfSample = true;
|
||||
imageSize.y += 1;
|
||||
BarcodeLocator.checkImageConstraints(inputStream, config.locator);
|
||||
expect(inputStream.getWidth()).to.be.equal(expected.x);
|
||||
expect(inputStream.getHeight()).to.be.equal(expected.y);
|
||||
});
|
||||
|
||||
it('should adjust the image-size', function() {
|
||||
var expected = {x: imageSize.x, y: imageSize.y};
|
||||
|
||||
imageSize.y += 1;
|
||||
config.locator.halfSample = false;
|
||||
BarcodeLocator.checkImageConstraints(inputStream, config.locator);
|
||||
expect(inputStream.getHeight()).to.be.equal(expected.y);
|
||||
expect(inputStream.getWidth()).to.be.equal(expected.x);
|
||||
});
|
||||
|
||||
it("should take the defined area into account", function() {
|
||||
var expectedSize = {
|
||||
x: 420,
|
||||
y: 315
|
||||
},
|
||||
expectedTopRight = {
|
||||
x: 115,
|
||||
y: 52
|
||||
},
|
||||
expectedCanvasSize = {
|
||||
x: 640,
|
||||
y: 480
|
||||
};
|
||||
|
||||
streamConfig.area = {
|
||||
top: "11%",
|
||||
right: "15%",
|
||||
bottom: "20%",
|
||||
left: "18%"
|
||||
};
|
||||
|
||||
config.locator.halfSample = false;
|
||||
BarcodeLocator.checkImageConstraints(inputStream, config.locator);
|
||||
expect(inputStream.getHeight()).to.be.equal(expectedSize.y);
|
||||
expect(inputStream.getWidth()).to.be.equal(expectedSize.x);
|
||||
expect(inputStream.setTopRight.getCall(0).args[0]).to.deep.equal(expectedTopRight);
|
||||
expect(inputStream.setCanvasSize.getCall(0).args[0]).to.deep.equal(expectedCanvasSize);
|
||||
});
|
||||
|
||||
it("should return the original size if set to full image", function() {
|
||||
var expectedSize = {
|
||||
x: 640,
|
||||
y: 480
|
||||
},
|
||||
expectedTopRight = {
|
||||
x: 0,
|
||||
y: 0
|
||||
},
|
||||
expectedCanvasSize = {
|
||||
x: 640,
|
||||
y: 480
|
||||
};
|
||||
|
||||
streamConfig.area = {
|
||||
top: "0%",
|
||||
right: "0%",
|
||||
bottom: "0%",
|
||||
left: "0%"
|
||||
};
|
||||
|
||||
config.locator.halfSample = false;
|
||||
BarcodeLocator.checkImageConstraints(inputStream, config.locator);
|
||||
expect(inputStream.getHeight()).to.be.equal(expectedSize.y);
|
||||
expect(inputStream.getWidth()).to.be.equal(expectedSize.x);
|
||||
expect(inputStream.setTopRight.getCall(0).args[0]).to.deep.equal(expectedTopRight);
|
||||
expect(inputStream.setCanvasSize.getCall(0).args[0]).to.deep.equal(expectedCanvasSize);
|
||||
});
|
||||
});
|
||||
});
|
||||
+69
-23
@@ -1,17 +1,15 @@
|
||||
define(['camera_access'], function(CameraAccess){
|
||||
var originalURL,
|
||||
originalUserMedia,
|
||||
originalMediaStreamTrack,
|
||||
video,
|
||||
stream;
|
||||
|
||||
|
||||
beforeEach(function() {
|
||||
var tracks = [{
|
||||
stop: function() {}
|
||||
}];
|
||||
|
||||
originalURL = window.URL;
|
||||
originalUserMedia = window.getUserMedia;
|
||||
originalMediaStreamTrack = window.MediaStreamTrack;
|
||||
window.MediaStreamTrack = {};
|
||||
window.URL = null;
|
||||
@@ -23,10 +21,7 @@ define(['camera_access'], function(CameraAccess){
|
||||
}
|
||||
};
|
||||
sinon.spy(tracks[0], "stop");
|
||||
navigator.getUserMedia = function(constraints, cb) {
|
||||
cb(stream);
|
||||
};
|
||||
sinon.spy(navigator, "getUserMedia");
|
||||
|
||||
video = {
|
||||
src: null,
|
||||
addEventListener: function() {
|
||||
@@ -48,29 +43,80 @@ define(['camera_access'], function(CameraAccess){
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
navigator.getUserMedia = originalUserMedia;
|
||||
window.URL = originalURL;
|
||||
window.MediaStreamTrack = originalMediaStreamTrack;
|
||||
});
|
||||
|
||||
describe('request', function() {
|
||||
it('should request the camera', function(done) {
|
||||
CameraAccess.request(video, {}, function() {
|
||||
expect(navigator.getUserMedia.calledOnce).to.equal(true);
|
||||
expect(video.src).to.deep.equal(stream);
|
||||
done();
|
||||
describe('success', function() {
|
||||
beforeEach(function() {
|
||||
sinon.stub(navigator, "getUserMedia", function(constraints, success) {
|
||||
success(stream);
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
navigator.getUserMedia.restore();
|
||||
});
|
||||
describe('request', function () {
|
||||
it('should request the camera', function (done) {
|
||||
CameraAccess.request(video, {}, function () {
|
||||
expect(navigator.getUserMedia.calledOnce).to.equal(true);
|
||||
expect(video.src).to.deep.equal(stream);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('release', function () {
|
||||
it('should release the camera', function (done) {
|
||||
CameraAccess.request(video, {}, function () {
|
||||
expect(video.src).to.deep.equal(stream);
|
||||
CameraAccess.release();
|
||||
expect(video.src.getVideoTracks()).to.have.length(1);
|
||||
expect(video.src.getVideoTracks()[0].stop.calledOnce).to.equal(true);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('release', function() {
|
||||
it('should release the camera', function(done) {
|
||||
CameraAccess.request(video, {}, function() {
|
||||
expect(video.src).to.deep.equal(stream);
|
||||
CameraAccess.release();
|
||||
expect(video.src.getVideoTracks()).to.have.length(1);
|
||||
expect(video.src.getVideoTracks()[0].stop.calledOnce).to.equal(true);
|
||||
done();
|
||||
|
||||
describe('failure', function() {
|
||||
describe("permission denied", function(){
|
||||
before(function() {
|
||||
sinon.stub(navigator, "getUserMedia", function(constraints, success, failure) {
|
||||
failure(new Error());
|
||||
});
|
||||
});
|
||||
|
||||
after(function() {
|
||||
navigator.getUserMedia.restore();
|
||||
});
|
||||
|
||||
it('should throw if getUserMedia not available', function(done) {
|
||||
CameraAccess.request(video, {}, function(err) {
|
||||
expect(err).to.be.defined;
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("not available", function(){
|
||||
var originalGetUserMedia;
|
||||
|
||||
before(function() {
|
||||
originalGetUserMedia = navigator.getUserMedia;
|
||||
navigator.getUserMedia = undefined;
|
||||
});
|
||||
|
||||
after(function() {
|
||||
navigator.getUserMedia = originalGetUserMedia;
|
||||
});
|
||||
|
||||
it('should throw if getUserMedia not available', function(done) {
|
||||
CameraAccess.request(video, {}, function(err) {
|
||||
expect(err).to.be.defined;
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -8,4 +8,138 @@ define(['cv_utils'], function(CVUtils){
|
||||
expect(res.toVec2()[0]).to.equal(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe('calculatePatchSize', function() {
|
||||
it('should not throw an error in case of valid image size', function() {
|
||||
var expected = {x: 32, y: 32},
|
||||
patchSize = CVUtils.calculatePatchSize("medium", {x: 640, y: 480});
|
||||
|
||||
expect(patchSize).to.be.deep.equal(expected);
|
||||
});
|
||||
|
||||
it('should thow an error if image size it not valid', function() {
|
||||
var expected = {x: 32, y: 32},
|
||||
patchSize = CVUtils.calculatePatchSize("medium", {x: 640, y: 480});
|
||||
|
||||
expect(patchSize).to.be.deep.equal(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('_parseCSSDimensionValues', function() {
|
||||
it("should convert a percentual value correctly", function() {
|
||||
var expected = {
|
||||
value: 10,
|
||||
unit: "%"
|
||||
},
|
||||
result = CVUtils._parseCSSDimensionValues("10%");
|
||||
|
||||
expect(result).to.be.deep.equal(expected);
|
||||
});
|
||||
|
||||
it("should convert a 0% value correctly", function() {
|
||||
var expected = {
|
||||
value: 100,
|
||||
unit: "%"
|
||||
},
|
||||
result = CVUtils._parseCSSDimensionValues("100%");
|
||||
|
||||
expect(result).to.be.deep.equal(expected);
|
||||
});
|
||||
|
||||
it("should convert a 100% value correctly", function() {
|
||||
var expected = {
|
||||
value: 0,
|
||||
unit: "%"
|
||||
},
|
||||
result = CVUtils._parseCSSDimensionValues("0%");
|
||||
|
||||
expect(result).to.be.deep.equal(expected);
|
||||
});
|
||||
|
||||
it("should convert a pixel value to percentage", function() {
|
||||
var expected = {
|
||||
value: 26.3,
|
||||
unit: "%"
|
||||
},
|
||||
result = CVUtils._parseCSSDimensionValues("26.3px");
|
||||
|
||||
console.log(result);
|
||||
expect(result).to.be.deep.equal(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe("_dimensionsConverters", function(){
|
||||
var context;
|
||||
|
||||
beforeEach(function() {
|
||||
context = {
|
||||
width: 640,
|
||||
height: 480
|
||||
};
|
||||
});
|
||||
|
||||
it("should convert a top-value correclty", function() {
|
||||
var expected = 48,
|
||||
result = CVUtils._dimensionsConverters.top({value: 10, unit: "%"}, context);
|
||||
|
||||
expect(result).to.be.equal(expected);
|
||||
});
|
||||
|
||||
it("should convert a right-value correclty", function() {
|
||||
var expected = 640 - 128,
|
||||
result = CVUtils._dimensionsConverters.right({value: 20, unit: "%"}, context);
|
||||
|
||||
expect(result).to.be.equal(expected);
|
||||
});
|
||||
|
||||
it("should convert a bottom-value correclty", function() {
|
||||
var expected = 480 - 77,
|
||||
result = CVUtils._dimensionsConverters.bottom({value: 16, unit: "%"}, context);
|
||||
|
||||
expect(result).to.be.equal(expected);
|
||||
});
|
||||
|
||||
it("should convert a left-value correclty", function() {
|
||||
var expected = 57,
|
||||
result = CVUtils._dimensionsConverters.left({value: 9, unit: "%"}, context);
|
||||
|
||||
expect(result).to.be.equal(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe("computeImageArea", function() {
|
||||
it("should calculate an image-area", function() {
|
||||
var expected = {
|
||||
sx: 115,
|
||||
sy: 48,
|
||||
sw: 429,
|
||||
sh: 336
|
||||
},
|
||||
result = CVUtils.computeImageArea(640, 480, {
|
||||
top: "10%",
|
||||
right: "15%",
|
||||
bottom: "20%",
|
||||
left: "18%"
|
||||
});
|
||||
|
||||
expect(result).to.be.deep.equal(expected);
|
||||
});
|
||||
|
||||
it("should calculate full image-area", function() {
|
||||
var expected = {
|
||||
sx: 0,
|
||||
sy: 0,
|
||||
sw: 640,
|
||||
sh: 480
|
||||
},
|
||||
result = CVUtils.computeImageArea(640, 480, {
|
||||
top: "0%",
|
||||
right: "0%",
|
||||
bottom: "0%",
|
||||
left: "0%"
|
||||
});
|
||||
|
||||
expect(result).to.be.deep.equal(expected);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
+75
-47
@@ -35,6 +35,7 @@ define(['quagga', 'async'], function(Quagga, async) {
|
||||
Quagga.decodeSingle(config, function(result) {
|
||||
console.log(sample.name);
|
||||
expect(result.codeResult.code).to.equal(sample.result);
|
||||
expect(result.codeResult.format).to.equal(sample.format);
|
||||
callback();
|
||||
});
|
||||
}, function() {
|
||||
@@ -45,18 +46,22 @@ define(['quagga', 'async'], function(Quagga, async) {
|
||||
|
||||
describe("EAN", function() {
|
||||
var config = generateConfig(),
|
||||
testSet = [
|
||||
{"name": "image-001.jpg", "result": "3574660239843"},
|
||||
{"name": "image-002.jpg", "result": "8032754490297"},
|
||||
{"name": "image-003.jpg", "result": "4006209700068"},
|
||||
/* {"name": "image-004.jpg", "result": "9002233139084"}, */
|
||||
/* {"name": "image-005.jpg", "result": "8004030044005"}, */
|
||||
{"name": "image-006.jpg", "result": "4003626011159"},
|
||||
{"name": "image-007.jpg", "result": "2111220009686"},
|
||||
{"name": "image-008.jpg", "result": "9000275609022"},
|
||||
{"name": "image-009.jpg", "result": "9004593978587"},
|
||||
{"name": "image-010.jpg", "result": "9002244845578"}
|
||||
];
|
||||
testSet = [
|
||||
{"name": "image-001.jpg", "result": "3574660239843"},
|
||||
{"name": "image-002.jpg", "result": "8032754490297"},
|
||||
{"name": "image-003.jpg", "result": "4006209700068"},
|
||||
/* {"name": "image-004.jpg", "result": "9002233139084"}, */
|
||||
/* {"name": "image-005.jpg", "result": "8004030044005"}, */
|
||||
{"name": "image-006.jpg", "result": "4003626011159"},
|
||||
{"name": "image-007.jpg", "result": "2111220009686"},
|
||||
{"name": "image-008.jpg", "result": "9000275609022"},
|
||||
{"name": "image-009.jpg", "result": "9004593978587"},
|
||||
{"name": "image-010.jpg", "result": "9002244845578"}
|
||||
];
|
||||
|
||||
testSet.forEach(function(sample) {
|
||||
sample.format = "ean_13";
|
||||
});
|
||||
|
||||
config.decoder.readers = ['ean_reader'];
|
||||
_runTestSet(testSet, config);
|
||||
@@ -65,17 +70,21 @@ define(['quagga', 'async'], function(Quagga, async) {
|
||||
describe("Code128", function() {
|
||||
var config = generateConfig(),
|
||||
testSet = [
|
||||
{"name": "image-001.jpg", "result": "0001285112001000040801"},
|
||||
{"name": "image-002.jpg", "result": "FANAVF1461710"},
|
||||
{"name": "image-003.jpg", "result": "673023"},
|
||||
// {"name": "image-004.jpg", "result": "010210150301625334"},
|
||||
{"name": "image-005.jpg", "result": "419055603900009001012999"},
|
||||
{"name": "image-006.jpg", "result": "419055603900009001012999"},
|
||||
{"name": "image-007.jpg", "result": "T 000003552345"},
|
||||
{"name": "image-008.jpg", "result": "FANAVF1461710"},
|
||||
{"name": "image-009.jpg", "result": "0001285112001000040801"},
|
||||
{"name": "image-010.jpg", "result": "673023"}
|
||||
];
|
||||
{"name": "image-001.jpg", "result": "0001285112001000040801"},
|
||||
{"name": "image-002.jpg", "result": "FANAVF1461710"},
|
||||
// {"name": "image-003.jpg", "result": "673023"},
|
||||
{"name": "image-004.jpg", "result": "010210150301625334"},
|
||||
{"name": "image-005.jpg", "result": "419055603900009001012999"},
|
||||
{"name": "image-006.jpg", "result": "419055603900009001012999"},
|
||||
{"name": "image-007.jpg", "result": "T 000003552345"},
|
||||
{"name": "image-008.jpg", "result": "FANAVF1461710"},
|
||||
{"name": "image-009.jpg", "result": "0001285112001000040801"},
|
||||
{"name": "image-010.jpg", "result": "673023"}
|
||||
];
|
||||
|
||||
testSet.forEach(function(sample) {
|
||||
sample.format = "code_128";
|
||||
});
|
||||
|
||||
config.decoder.readers = ['code_128_reader'];
|
||||
_runTestSet(testSet, config);
|
||||
@@ -84,17 +93,20 @@ define(['quagga', 'async'], function(Quagga, async) {
|
||||
describe("Code39", function() {
|
||||
var config = generateConfig(),
|
||||
testSet = [
|
||||
{"name": "image-001.jpg", "result": "B3% $DAD$"},
|
||||
/*{"name": "image-002.jpg", "result": "QUAGGAJS"},*/
|
||||
{"name": "image-003.jpg", "result": "CODE39"},
|
||||
{"name": "image-004.jpg", "result": "QUAGGAJS"},
|
||||
/* {"name": "image-005.jpg", "result": "CODE39"}, */
|
||||
{"name": "image-006.jpg", "result": "2/4-8/16-32"},
|
||||
{"name": "image-007.jpg", "result": "2/4-8/16-32"},
|
||||
{"name": "image-008.jpg", "result": "CODE39"},
|
||||
{"name": "image-009.jpg", "result": "2/4-8/16-32"},
|
||||
{"name": "image-010.jpg", "result": "CODE39"}
|
||||
];
|
||||
{"name": "image-001.jpg", "result": "B3% $DAD$"},
|
||||
{"name": "image-003.jpg", "result": "CODE39"},
|
||||
{"name": "image-004.jpg", "result": "QUAGGAJS"},
|
||||
{"name": "image-005.jpg", "result": "CODE39"},
|
||||
{"name": "image-006.jpg", "result": "2/4-8/16-32"},
|
||||
{"name": "image-007.jpg", "result": "2/4-8/16-32"},
|
||||
{"name": "image-008.jpg", "result": "CODE39"},
|
||||
{"name": "image-009.jpg", "result": "2/4-8/16-32"},
|
||||
{"name": "image-010.jpg", "result": "CODE39"}
|
||||
];
|
||||
|
||||
testSet.forEach(function(sample) {
|
||||
sample.format = "code_39";
|
||||
});
|
||||
|
||||
config.decoder.readers = ['code_39_reader'];
|
||||
_runTestSet(testSet, config);
|
||||
@@ -103,17 +115,21 @@ define(['quagga', 'async'], function(Quagga, async) {
|
||||
describe("EAN-8", function() {
|
||||
var config = generateConfig(),
|
||||
testSet = [
|
||||
{"name": "image-001.jpg", "result": "42191605"},
|
||||
{"name": "image-002.jpg", "result": "42191605"},
|
||||
{"name": "image-003.jpg", "result": "90311208"},
|
||||
{"name": "image-004.jpg", "result": "24057257"},
|
||||
{"name": "image-005.jpg", "result": "90162602"},
|
||||
{"name": "image-006.jpg", "result": "24036153"},
|
||||
{"name": "image-007.jpg", "result": "42176817"},
|
||||
/*{"name": "image-008.jpg", "result": "42191605"},*/
|
||||
{"name": "image-009.jpg", "result": "42242215"},
|
||||
{"name": "image-010.jpg", "result": "42184799"}
|
||||
];
|
||||
{"name": "image-001.jpg", "result": "42191605"},
|
||||
{"name": "image-002.jpg", "result": "42191605"},
|
||||
{"name": "image-003.jpg", "result": "90311208"},
|
||||
{"name": "image-004.jpg", "result": "24057257"},
|
||||
{"name": "image-005.jpg", "result": "90162602"},
|
||||
{"name": "image-006.jpg", "result": "24036153"},
|
||||
{"name": "image-007.jpg", "result": "42176817"},
|
||||
{"name": "image-008.jpg", "result": "42191605"},
|
||||
{"name": "image-009.jpg", "result": "42242215"},
|
||||
{"name": "image-010.jpg", "result": "42184799"}
|
||||
];
|
||||
|
||||
testSet.forEach(function(sample) {
|
||||
sample.format = "ean_8";
|
||||
});
|
||||
|
||||
config.decoder.readers = ['ean_8_reader'];
|
||||
_runTestSet(testSet, config);
|
||||
@@ -127,13 +143,17 @@ define(['quagga', 'async'], function(Quagga, async) {
|
||||
{"name": "image-003.jpg", "result": "882428015084"},
|
||||
{"name": "image-004.jpg", "result": "882428015343"},
|
||||
{"name": "image-005.jpg", "result": "882428015343"},
|
||||
{"name": "image-006.jpg", "result": "882428015046"},
|
||||
/* {"name": "image-006.jpg", "result": "882428015046"}, */
|
||||
{"name": "image-007.jpg", "result": "882428015084"},
|
||||
{"name": "image-008.jpg", "result": "882428015046"},
|
||||
{"name": "image-009.jpg", "result": "039047013551"},
|
||||
{"name": "image-010.jpg", "result": "039047013551"}
|
||||
];
|
||||
|
||||
testSet.forEach(function(sample) {
|
||||
sample.format = "upc_a";
|
||||
});
|
||||
|
||||
config.decoder.readers = ['upc_reader'];
|
||||
_runTestSet(testSet, config);
|
||||
});
|
||||
@@ -153,6 +173,10 @@ define(['quagga', 'async'], function(Quagga, async) {
|
||||
{"name": "image-010.jpg", "result": "01264904"}
|
||||
];
|
||||
|
||||
testSet.forEach(function(sample) {
|
||||
sample.format = "upc_e";
|
||||
});
|
||||
|
||||
config.decoder.readers = ['upc_e_reader'];
|
||||
_runTestSet(testSet, config);
|
||||
});
|
||||
@@ -167,11 +191,15 @@ define(['quagga', 'async'], function(Quagga, async) {
|
||||
{"name": "image-005.jpg", "result": "C$399.95A"},
|
||||
{"name": "image-006.jpg", "result": "B546745735B"},
|
||||
{"name": "image-007.jpg", "result": "C$399.95A"},
|
||||
/* {"name": "image-008.jpg", "result": "01264904"}, */
|
||||
{"name": "image-008.jpg", "result": "A16:9/4:3/3:2D"},
|
||||
{"name": "image-009.jpg", "result": "C$399.95A"},
|
||||
{"name": "image-010.jpg", "result": "C$399.95A"}
|
||||
];
|
||||
|
||||
testSet.forEach(function(sample) {
|
||||
sample.format = "codabar";
|
||||
});
|
||||
|
||||
config.decoder.readers = ['codabar_reader'];
|
||||
_runTestSet(testSet, config);
|
||||
});
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
|
||||
define(['result_collector', 'image_debug'], function(ResultCollector, ImageDebug) {
|
||||
var canvasMock,
|
||||
imageSize,
|
||||
config;
|
||||
|
||||
beforeEach(function() {
|
||||
imageSize = {x: 320, y: 240};
|
||||
config = {
|
||||
capture: true,
|
||||
capacity: 20,
|
||||
blacklist: [{code: "3574660239843", format: "ean_13"}],
|
||||
filter: function(codeResult) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
canvasMock = {
|
||||
getContext: function() {
|
||||
return {};
|
||||
},
|
||||
toDataURL: sinon.spy(),
|
||||
width: 0,
|
||||
height: 0
|
||||
};
|
||||
sinon.stub(document, "createElement", function(type) {
|
||||
if (type === "canvas") {
|
||||
return canvasMock;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
document.createElement.restore();
|
||||
});
|
||||
|
||||
|
||||
describe('create', function () {
|
||||
it("should return a new collector", function() {
|
||||
ResultCollector.create(config);
|
||||
expect(document.createElement.calledOnce).to.be.equal(true);
|
||||
expect(document.createElement.getCall(0).args[0]).to.equal("canvas");
|
||||
});
|
||||
});
|
||||
|
||||
describe('addResult', function() {
|
||||
beforeEach(function() {
|
||||
sinon.stub(ImageDebug, "drawImage", function() {});
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
ImageDebug.drawImage.restore();
|
||||
});
|
||||
|
||||
it("should not add result if capacity is full", function(){
|
||||
config.capacity = 1;
|
||||
var collector = ResultCollector.create(config);
|
||||
collector.addResult([], imageSize, {});
|
||||
collector.addResult([], imageSize, {});
|
||||
collector.addResult([], imageSize, {});
|
||||
expect(collector.getResults()).to.have.length(1);
|
||||
});
|
||||
|
||||
it("should only add results which match constraints", function(){
|
||||
var collector = ResultCollector.create(config),
|
||||
results;
|
||||
|
||||
collector.addResult([], imageSize, {code: "423423443", format: "ean_13"});
|
||||
collector.addResult([], imageSize, {code: "3574660239843", format: "ean_13"});
|
||||
collector.addResult([], imageSize, {code: "3574660239843", format: "code_128"});
|
||||
|
||||
results = collector.getResults();
|
||||
expect(results).to.have.length(2);
|
||||
|
||||
results.forEach(function(result) {
|
||||
expect(result).not.to.deep.equal(config.blacklist[0]);
|
||||
});
|
||||
});
|
||||
|
||||
it("should add result if no filter is set", function() {
|
||||
delete config.filter;
|
||||
var collector = ResultCollector.create(config);
|
||||
|
||||
collector.addResult([], imageSize, {code: "423423443", format: "ean_13"});
|
||||
expect(collector.getResults()).to.have.length(1);
|
||||
});
|
||||
|
||||
it("should not add results if filter returns false", function() {
|
||||
config.filter = function(){ return false };
|
||||
var collector = ResultCollector.create(config);
|
||||
|
||||
collector.addResult([], imageSize, {code: "423423443", format: "ean_13"});
|
||||
expect(collector.getResults()).to.have.length(0);
|
||||
});
|
||||
|
||||
it("should add result if no blacklist is set", function() {
|
||||
delete config.blacklist;
|
||||
var collector = ResultCollector.create(config);
|
||||
|
||||
collector.addResult([], imageSize, {code: "3574660239843", format: "ean_13"});
|
||||
expect(collector.getResults()).to.have.length(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
+3
-10
@@ -49,8 +49,7 @@ define([
|
||||
overlay : null
|
||||
}
|
||||
},
|
||||
_barcodeReaders = [],
|
||||
_barcodeReader = null;
|
||||
_barcodeReaders = [];
|
||||
|
||||
initCanvas();
|
||||
initReaders();
|
||||
@@ -135,13 +134,10 @@ define([
|
||||
|
||||
// check if inside image
|
||||
extendLine(ext);
|
||||
while (ext > 1 && !inputImageWrapper.inImageWithBorder(line[0], 0) || !inputImageWrapper.inImageWithBorder(line[1], 0)) {
|
||||
ext -= Math.floor(ext/2);
|
||||
while (ext > 1 && (!inputImageWrapper.inImageWithBorder(line[0], 0) || !inputImageWrapper.inImageWithBorder(line[1], 0))) {
|
||||
ext -= Math.ceil(ext/2);
|
||||
extendLine(-ext);
|
||||
}
|
||||
if (ext <= 1) {
|
||||
return null;
|
||||
}
|
||||
return line;
|
||||
}
|
||||
|
||||
@@ -171,9 +167,6 @@ define([
|
||||
|
||||
for ( i = 0; i < _barcodeReaders.length && result === null; i++) {
|
||||
result = _barcodeReaders[i].decodePattern(barcodeLine.line);
|
||||
if (result !== null) {
|
||||
_barcodeReader = _barcodeReaders[i];
|
||||
}
|
||||
}
|
||||
if(result === null){
|
||||
return null;
|
||||
|
||||
+40
-2
@@ -486,10 +486,11 @@ function(ImageWrapper, CVUtils, Rasterizer, Tracer, skeletonizer, ArrayHelper, I
|
||||
initBuffers();
|
||||
initCanvas();
|
||||
},
|
||||
|
||||
locate : function() {
|
||||
var patchesFound,
|
||||
topLabels = [],
|
||||
boxes = [];
|
||||
topLabels,
|
||||
boxes;
|
||||
|
||||
if (_config.halfSample) {
|
||||
CVUtils.halfSample(_inputImageWrapper, _currentImageWrapper);
|
||||
@@ -516,6 +517,43 @@ function(ImageWrapper, CVUtils, Rasterizer, Tracer, skeletonizer, ArrayHelper, I
|
||||
|
||||
boxes = findBoxes(topLabels, maxLabel);
|
||||
return boxes;
|
||||
},
|
||||
|
||||
checkImageConstraints: function(inputStream, config) {
|
||||
var patchSize,
|
||||
width = inputStream.getWidth(),
|
||||
height = inputStream.getHeight(),
|
||||
halfSample = config.halfSample ? 0.5 : 1,
|
||||
size,
|
||||
area;
|
||||
|
||||
// calculate width and height based on area
|
||||
if (inputStream.getConfig().area) {
|
||||
area = CVUtils.computeImageArea(width, height, inputStream.getConfig().area);
|
||||
inputStream.setTopRight({x: area.sx, y: area.sy});
|
||||
inputStream.setCanvasSize({x: width, y: height});
|
||||
width = area.sw;
|
||||
height = area.sh;
|
||||
}
|
||||
|
||||
size = {
|
||||
x: Math.floor(width * halfSample),
|
||||
y: Math.floor(height * halfSample)
|
||||
};
|
||||
|
||||
patchSize = CVUtils.calculatePatchSize(config.patchSize, size);
|
||||
console.log("Patch-Size: " + JSON.stringify(patchSize));
|
||||
|
||||
inputStream.setWidth(Math.floor(Math.floor(size.x/patchSize.x)*(1/halfSample)*patchSize.x));
|
||||
inputStream.setHeight(Math.floor(Math.floor(size.y/patchSize.y)*(1/halfSample)*patchSize.y));
|
||||
|
||||
if ((inputStream.getWidth() % patchSize.x) === 0 && (inputStream.getHeight() % patchSize.y) === 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
throw new Error("Image dimensions do not comply with the current settings: Width (" +
|
||||
width + " )and height (" + height +
|
||||
") must a multiple of " + patchSize.x);
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
@@ -166,6 +166,9 @@ define(
|
||||
} else {
|
||||
result.direction = BarcodeReader.DIRECTION.FORWARD;
|
||||
}
|
||||
if (result) {
|
||||
result.format = self.FORMAT;
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
@@ -180,6 +183,11 @@ define(
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
Object.defineProperty(BarcodeReader.prototype, "FORMAT", {
|
||||
value: 'unknown',
|
||||
writeable: false
|
||||
});
|
||||
|
||||
BarcodeReader.DIRECTION = {
|
||||
FORWARD : 1,
|
||||
|
||||
+5
-3
@@ -117,6 +117,7 @@ define(["cv_utils", "image_wrapper"], function(CVUtils, ImageWrapper) {
|
||||
max = result.max,
|
||||
line = result.line,
|
||||
slope,
|
||||
slope2,
|
||||
center = min + (max - min) / 2,
|
||||
extrema = [],
|
||||
currentDir,
|
||||
@@ -132,11 +133,12 @@ define(["cv_utils", "image_wrapper"], function(CVUtils, ImageWrapper) {
|
||||
pos : 0,
|
||||
val : line[0]
|
||||
});
|
||||
for ( i = 0; i < line.length - 1; i++) {
|
||||
for ( i = 0; i < line.length - 2; i++) {
|
||||
slope = (line[i + 1] - line[i]);
|
||||
if (slope < rThreshold && line[i + 1] < (center*1.5)) {
|
||||
slope2 = (line[i + 2] - line[i + 1]);
|
||||
if ((slope + slope2) < rThreshold && line[i + 1] < (center*1.5)) {
|
||||
dir = Slope.DIR.DOWN;
|
||||
} else if (slope > threshold && line[i + 1] > (center*0.5)) {
|
||||
} else if ((slope + slope2) > threshold && line[i + 1] > (center*0.5)) {
|
||||
dir = Slope.DIR.UP;
|
||||
} else {
|
||||
dir = currentDir;
|
||||
|
||||
+11
-7
@@ -13,11 +13,15 @@ define(["html_utils"], function(HtmlUtils) {
|
||||
* @param {Object} failure Callback
|
||||
*/
|
||||
function getUserMedia(constraints, success, failure) {
|
||||
navigator.getUserMedia(constraints, function(stream) {
|
||||
streamRef = stream;
|
||||
var videoSrc = (window.URL && window.URL.createObjectURL(stream)) || stream;
|
||||
success.apply(null, [videoSrc]);
|
||||
}, failure);
|
||||
if (typeof navigator.getUserMedia !== 'undefined') {
|
||||
navigator.getUserMedia(constraints, function (stream) {
|
||||
streamRef = stream;
|
||||
var videoSrc = (window.URL && window.URL.createObjectURL(stream)) || stream;
|
||||
success.apply(null, [videoSrc]);
|
||||
}, failure);
|
||||
} else {
|
||||
failure(new TypeError("getUserMedia not available"));
|
||||
}
|
||||
}
|
||||
|
||||
function loadedData(video, callback) {
|
||||
@@ -56,7 +60,7 @@ define(["html_utils"], function(HtmlUtils) {
|
||||
video.addEventListener('loadeddata', loadedDataHandler, false);
|
||||
video.play();
|
||||
}, function(e) {
|
||||
console.log(e);
|
||||
callback(e);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -79,7 +83,7 @@ define(["html_utils"], function(HtmlUtils) {
|
||||
facing: "environment"
|
||||
}, config);
|
||||
|
||||
if ( typeof MediaStreamTrack.getSources !== 'undefined') {
|
||||
if ( typeof MediaStreamTrack !== 'undefined' && typeof MediaStreamTrack.getSources !== 'undefined') {
|
||||
MediaStreamTrack.getSources(function(sourceInfos) {
|
||||
var videoSourceId;
|
||||
for (var i = 0; i != sourceInfos.length; ++i) {
|
||||
|
||||
@@ -20,7 +20,8 @@ define(
|
||||
START_END: {value: [0x01A, 0x029, 0x00B, 0x00E]},
|
||||
MIN_ENCODED_CHARS: {value: 4},
|
||||
MAX_ACCEPTABLE: {value: 2.0},
|
||||
PADDING: {value: 1.5}
|
||||
PADDING: {value: 1.5},
|
||||
FORMAT: {value: "codabar", writeable: false}
|
||||
};
|
||||
|
||||
CodabarReader.prototype = Object.create(BarcodeReader.prototype, properties);
|
||||
|
||||
+42
-69
@@ -132,7 +132,8 @@ define(
|
||||
[2, 3, 3, 1, 1, 1, 2]
|
||||
]},
|
||||
SINGLE_CODE_ERROR: {value: 1},
|
||||
AVG_CODE_ERROR: {value: 0.5}
|
||||
AVG_CODE_ERROR: {value: 0.5},
|
||||
FORMAT: {value: "code_128", writeable: false}
|
||||
};
|
||||
|
||||
Code128Reader.prototype = Object.create(BarcodeReader.prototype, properties);
|
||||
@@ -161,67 +162,17 @@ define(
|
||||
} else {
|
||||
if (counterPos === counter.length - 1) {
|
||||
normalized = self._normalize(counter);
|
||||
for ( code = 0; code < self.CODE_PATTERN.length; code++) {
|
||||
error = self._matchPattern(normalized, self.CODE_PATTERN[code]);
|
||||
if (error < bestMatch.error) {
|
||||
bestMatch.code = code;
|
||||
bestMatch.error = error;
|
||||
if (normalized) {
|
||||
for (code = 0; code < self.CODE_PATTERN.length; code++) {
|
||||
error = self._matchPattern(normalized, self.CODE_PATTERN[code]);
|
||||
if (error < bestMatch.error) {
|
||||
bestMatch.code = code;
|
||||
bestMatch.error = error;
|
||||
}
|
||||
}
|
||||
}
|
||||
bestMatch.end = i;
|
||||
return bestMatch;
|
||||
} else {
|
||||
counterPos++;
|
||||
}
|
||||
counter[counterPos] = 1;
|
||||
isWhite = !isWhite;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
Code128Reader.prototype._findEnd = function() {
|
||||
var counter = [0, 0, 0, 0, 0, 0, 0],
|
||||
i,
|
||||
self = this,
|
||||
offset = self._nextSet(self._row),
|
||||
isWhite = !self._row[offset],
|
||||
counterPos = 0,
|
||||
bestMatch = {
|
||||
error : Number.MAX_VALUE,
|
||||
code : -1,
|
||||
start : 0,
|
||||
end : 0
|
||||
},
|
||||
error,
|
||||
j,
|
||||
sum,
|
||||
normalized;
|
||||
|
||||
for ( i = offset; i < self._row.length; i++) {
|
||||
if (self._row[i] ^ isWhite) {
|
||||
counter[counterPos]++;
|
||||
} else {
|
||||
if (counterPos === counter.length - 1) {
|
||||
sum = 0;
|
||||
for ( j = 0; j < counter.length; j++) {
|
||||
sum += counter[j];
|
||||
}
|
||||
normalized = self._normalize(counter, 13);
|
||||
error = self._matchPattern(normalized, self.CODE_PATTERN[self.STOP_CODE]);
|
||||
if (error < self.AVG_CODE_ERROR) {
|
||||
bestMatch.error = error;
|
||||
bestMatch.start = i - sum;
|
||||
bestMatch.end = i;
|
||||
return bestMatch;
|
||||
}
|
||||
|
||||
for ( j = 0; j < 5; j++) {
|
||||
counter[j] = counter[j + 2];
|
||||
}
|
||||
counter[5] = 0;
|
||||
counter[6] = 0;
|
||||
counterPos--;
|
||||
} else {
|
||||
counterPos++;
|
||||
}
|
||||
@@ -261,17 +212,19 @@ define(
|
||||
sum += counter[j];
|
||||
}
|
||||
normalized = self._normalize(counter);
|
||||
for ( code = self.START_CODE_A; code <= self.START_CODE_C; code++) {
|
||||
error = self._matchPattern(normalized, self.CODE_PATTERN[code]);
|
||||
if (error < bestMatch.error) {
|
||||
bestMatch.code = code;
|
||||
bestMatch.error = error;
|
||||
if (normalized) {
|
||||
for (code = self.START_CODE_A; code <= self.START_CODE_C; code++) {
|
||||
error = self._matchPattern(normalized, self.CODE_PATTERN[code]);
|
||||
if (error < bestMatch.error) {
|
||||
bestMatch.code = code;
|
||||
bestMatch.error = error;
|
||||
}
|
||||
}
|
||||
if (bestMatch.error < self.AVG_CODE_ERROR) {
|
||||
bestMatch.start = i - sum;
|
||||
bestMatch.end = i;
|
||||
return bestMatch;
|
||||
}
|
||||
}
|
||||
if (bestMatch.error < self.AVG_CODE_ERROR) {
|
||||
bestMatch.start = i - sum;
|
||||
bestMatch.end = i;
|
||||
return bestMatch;
|
||||
}
|
||||
|
||||
for ( j = 0; j < 4; j++) {
|
||||
@@ -420,7 +373,7 @@ define(
|
||||
|
||||
// find end bar
|
||||
code.end = self._nextUnset(self._row, code.end);
|
||||
if (code.end === self._row.length) {
|
||||
if(!self._verifyTrailingWhitespace(code)){
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -431,9 +384,15 @@ define(
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!result.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// remove last code from result (checksum)
|
||||
result.splice(result.length - 1, 1);
|
||||
|
||||
|
||||
|
||||
return {
|
||||
code : result.join(""),
|
||||
start : startInfo.start,
|
||||
@@ -444,6 +403,20 @@ define(
|
||||
endInfo : code
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
BarcodeReader.prototype._verifyTrailingWhitespace = function(endInfo) {
|
||||
var self = this,
|
||||
trailingWhitespaceEnd;
|
||||
|
||||
trailingWhitespaceEnd = endInfo.end + ((endInfo.end - endInfo.start) / 2);
|
||||
if (trailingWhitespaceEnd < self._row.length) {
|
||||
if (self._matchRange(endInfo.end, trailingWhitespaceEnd, 0)) {
|
||||
return endInfo;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
return (Code128Reader);
|
||||
}
|
||||
|
||||
+19
-1
@@ -17,7 +17,8 @@ define(
|
||||
ALPHABETH_STRING: {value: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. *$/+%"},
|
||||
ALPHABET: {value: [48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 45, 46, 32, 42, 36, 47, 43, 37]},
|
||||
CHARACTER_ENCODINGS: {value: [0x034, 0x121, 0x061, 0x160, 0x031, 0x130, 0x070, 0x025, 0x124, 0x064, 0x109, 0x049, 0x148, 0x019, 0x118, 0x058, 0x00D, 0x10C, 0x04C, 0x01C, 0x103, 0x043, 0x142, 0x013, 0x112, 0x052, 0x007, 0x106, 0x046, 0x016, 0x181, 0x0C1, 0x1C0, 0x091, 0x190, 0x0D0, 0x085, 0x184, 0x0C4, 0x094, 0x0A8, 0x0A2, 0x08A, 0x02A]},
|
||||
ASTERISK: {value: 0x094}
|
||||
ASTERISK: {value: 0x094},
|
||||
FORMAT: {value: "code_39", writeable: false}
|
||||
};
|
||||
|
||||
Code39Reader.prototype = Object.create(BarcodeReader.prototype, properties);
|
||||
@@ -82,7 +83,13 @@ define(
|
||||
} while(decodedChar !== '*');
|
||||
result.pop();
|
||||
|
||||
if (!result.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if(!self._verifyTrailingWhitespace(lastStart, nextStart, counters)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
code : result.join(""),
|
||||
@@ -93,6 +100,17 @@ define(
|
||||
};
|
||||
};
|
||||
|
||||
Code39Reader.prototype._verifyTrailingWhitespace = function(lastStart, nextStart, counters) {
|
||||
var trailingWhitespaceEnd,
|
||||
patternSize = ArrayHelper.sum(counters);
|
||||
|
||||
trailingWhitespaceEnd = nextStart - lastStart - patternSize;
|
||||
if ((trailingWhitespaceEnd * 3) >= patternSize) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
Code39Reader.prototype._patternToChar = function(pattern) {
|
||||
var i,
|
||||
self = this;
|
||||
|
||||
+8
-1
@@ -12,7 +12,14 @@ define(function(){
|
||||
minAspectRatio: 0,
|
||||
maxAspectRatio: 100,
|
||||
facing: "environment" // or user
|
||||
}
|
||||
},
|
||||
area: {
|
||||
top: "0%",
|
||||
right: "0%",
|
||||
left: "0%",
|
||||
bottom: "0%"
|
||||
},
|
||||
singleChannel: false // true: only the red color-channel is read
|
||||
},
|
||||
tracking: false,
|
||||
debug: false,
|
||||
|
||||
+64
-15
@@ -484,13 +484,19 @@ define(['cluster', 'glMatrixAddon', "array_helper"], function(Cluster2, glMatrix
|
||||
|
||||
};
|
||||
|
||||
CVUtils.computeGray = function(imageData, outArray) {
|
||||
var l = imageData.length / 4;
|
||||
var i = 0;
|
||||
for ( i = 0; i < l; i++) {
|
||||
//outArray[i] = (0.299*imageData[i*4+0] + 0.587*imageData[i*4+1] + 0.114*imageData[i*4+2]);
|
||||
CVUtils.computeGray = function(imageData, outArray, config) {
|
||||
var l = (imageData.length / 4) | 0,
|
||||
i,
|
||||
singleChannel = config && config.singleChannel === true;
|
||||
|
||||
outArray[i] = Math.floor(0.299 * imageData[i * 4 + 0] + 0.587 * imageData[i * 4 + 1] + 0.114 * imageData[i * 4 + 2]);
|
||||
if (singleChannel) {
|
||||
for (i = 0; i < l; i++) {
|
||||
outArray[i] = imageData[i * 4 + 0];
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < l; i++) {
|
||||
outArray[i] = Math.floor(0.299 * imageData[i * 4 + 0] + 0.587 * imageData[i * 4 + 1] + 0.114 * imageData[i * 4 + 2]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -647,21 +653,64 @@ define(['cluster', 'glMatrixAddon', "array_helper"], function(Cluster2, glMatrix
|
||||
optimalPatchSize = findPatchSizeForDivisors(common);
|
||||
if (!optimalPatchSize) {
|
||||
optimalPatchSize = findPatchSizeForDivisors(this._computeDivisors(wideSide));
|
||||
throw new AdjustToSizeError("", optimalPatchSize);
|
||||
if (!optimalPatchSize) {
|
||||
optimalPatchSize = findPatchSizeForDivisors((this._computeDivisors(desiredPatchSize * nrOfPatches)));
|
||||
}
|
||||
}
|
||||
return optimalPatchSize;
|
||||
};
|
||||
|
||||
function AdjustToSizeError(message, desiredPatchSize) {
|
||||
this.name = 'AdjustToSizeError';
|
||||
this.message = message || 'AdjustToSizeError';
|
||||
this.patchSize = desiredPatchSize;
|
||||
}
|
||||
CVUtils._parseCSSDimensionValues = function(value) {
|
||||
var dimension = {
|
||||
value: parseFloat(value),
|
||||
unit: value.indexOf("%") === value.length-1 ? "%" : "%"
|
||||
};
|
||||
|
||||
AdjustToSizeError.prototype = Object.create(RangeError.prototype);
|
||||
AdjustToSizeError.prototype.constructor = AdjustToSizeError;
|
||||
return dimension;
|
||||
};
|
||||
|
||||
CVUtils.AdjustToSizeError = AdjustToSizeError;
|
||||
CVUtils._dimensionsConverters = {
|
||||
top: function(dimension, context) {
|
||||
if (dimension.unit === "%") {
|
||||
return Math.floor(context.height * (dimension.value / 100));
|
||||
}
|
||||
},
|
||||
right: function(dimension, context) {
|
||||
if (dimension.unit === "%") {
|
||||
return Math.floor(context.width - (context.width * (dimension.value / 100)));
|
||||
}
|
||||
},
|
||||
bottom: function(dimension, context) {
|
||||
if (dimension.unit === "%") {
|
||||
return Math.floor(context.height - (context.height * (dimension.value / 100)));
|
||||
}
|
||||
},
|
||||
left: function(dimension, context) {
|
||||
if (dimension.unit === "%") {
|
||||
return Math.floor(context.width * (dimension.value / 100));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
CVUtils.computeImageArea = function(inputWidth, inputHeight, area) {
|
||||
var context = {width: inputWidth, height: inputHeight};
|
||||
|
||||
var parsedArea = Object.keys(area).reduce(function(result, key) {
|
||||
var value = area[key],
|
||||
parsed = CVUtils._parseCSSDimensionValues(value),
|
||||
calculated = CVUtils._dimensionsConverters[key](parsed, context);
|
||||
|
||||
result[key] = calculated;
|
||||
return result;
|
||||
}, {});
|
||||
|
||||
return {
|
||||
sx: parsedArea.left,
|
||||
sy: parsedArea.top,
|
||||
sw: parsedArea.right - parsedArea.left,
|
||||
sh: parsedArea.bottom - parsedArea.top
|
||||
};
|
||||
};
|
||||
|
||||
return (CVUtils);
|
||||
});
|
||||
|
||||
+6
-2
@@ -12,7 +12,11 @@ define(
|
||||
EANReader.call(this);
|
||||
}
|
||||
|
||||
EAN8Reader.prototype = Object.create(EANReader.prototype);
|
||||
var properties = {
|
||||
FORMAT: {value: "ean_8", writeable: false}
|
||||
};
|
||||
|
||||
EAN8Reader.prototype = Object.create(EANReader.prototype, properties);
|
||||
EAN8Reader.prototype.constructor = EAN8Reader;
|
||||
|
||||
EAN8Reader.prototype._decodePayload = function(code, result, decodedCodes) {
|
||||
@@ -28,7 +32,7 @@ define(
|
||||
decodedCodes.push(code);
|
||||
}
|
||||
|
||||
code = self._findPattern(self.MIDDLE_PATTERN, code.end, true);
|
||||
code = self._findPattern(self.MIDDLE_PATTERN, code.end, true, false);
|
||||
if (code === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
+23
-18
@@ -42,8 +42,9 @@ define(
|
||||
[2, 1, 1, 3]
|
||||
]},
|
||||
CODE_FREQUENCY : {value: [0, 11, 13, 14, 19, 25, 28, 21, 22, 26]},
|
||||
SINGLE_CODE_ERROR: {value: 0.7},
|
||||
AVG_CODE_ERROR: {value: 0.3}
|
||||
SINGLE_CODE_ERROR: {value: 0.67},
|
||||
AVG_CODE_ERROR: {value: 0.27},
|
||||
FORMAT: {value: "ean_13", writeable: false}
|
||||
};
|
||||
|
||||
EANReader.prototype = Object.create(BarcodeReader.prototype, properties);
|
||||
@@ -76,18 +77,20 @@ define(
|
||||
} else {
|
||||
if (counterPos === counter.length - 1) {
|
||||
normalized = self._normalize(counter);
|
||||
for ( code = 0; code < coderange; code++) {
|
||||
error = self._matchPattern(normalized, self.CODE_PATTERN[code]);
|
||||
if (error < bestMatch.error) {
|
||||
bestMatch.code = code;
|
||||
bestMatch.error = error;
|
||||
if (normalized) {
|
||||
for (code = 0; code < coderange; code++) {
|
||||
error = self._matchPattern(normalized, self.CODE_PATTERN[code]);
|
||||
if (error < bestMatch.error) {
|
||||
bestMatch.code = code;
|
||||
bestMatch.error = error;
|
||||
}
|
||||
}
|
||||
bestMatch.end = i;
|
||||
if (bestMatch.error > self.AVG_CODE_ERROR) {
|
||||
return null;
|
||||
}
|
||||
return bestMatch;
|
||||
}
|
||||
bestMatch.end = i;
|
||||
if (bestMatch.error > self.AVG_CODE_ERROR) {
|
||||
return null;
|
||||
}
|
||||
return bestMatch;
|
||||
} else {
|
||||
counterPos++;
|
||||
}
|
||||
@@ -144,13 +147,15 @@ define(
|
||||
sum += counter[j];
|
||||
}
|
||||
normalized = self._normalize(counter);
|
||||
error = self._matchPattern(normalized, pattern);
|
||||
if (normalized) {
|
||||
error = self._matchPattern(normalized, pattern);
|
||||
|
||||
if (error < epsilon) {
|
||||
bestMatch.error = error;
|
||||
bestMatch.start = i - sum;
|
||||
bestMatch.end = i;
|
||||
return bestMatch;
|
||||
if (error < epsilon) {
|
||||
bestMatch.error = error;
|
||||
bestMatch.start = i - sum;
|
||||
bestMatch.end = i;
|
||||
return bestMatch;
|
||||
}
|
||||
}
|
||||
if (tryHarder) {
|
||||
for ( j = 0; j < counter.length - 2; j++) {
|
||||
|
||||
+17
-20
@@ -10,29 +10,26 @@ define(["cv_utils"], function(CVUtils) {
|
||||
var _that = {},
|
||||
_streamConfig = inputStream.getConfig(),
|
||||
_video_size = CVUtils.imageRef(inputStream.getRealWidth(), inputStream.getRealHeight()),
|
||||
_size =_streamConfig.size ? CVUtils.imageRef(inputStream.getWidth(), inputStream.getHeight()) : _video_size,
|
||||
_sx = 0,
|
||||
_sy = 0,
|
||||
_dx = 0,
|
||||
_dy = 0,
|
||||
_sWidth,
|
||||
_dWidth,
|
||||
_sHeight,
|
||||
_dHeight,
|
||||
_canvas = null,
|
||||
_canvasSize = inputStream.getCanvasSize(),
|
||||
_size = CVUtils.imageRef(inputStream.getWidth(), inputStream.getHeight()),
|
||||
topRight = inputStream.getTopRight(),
|
||||
_sx = topRight.x,
|
||||
_sy = topRight.y,
|
||||
_canvas,
|
||||
_ctx = null,
|
||||
_data = null;
|
||||
|
||||
_sWidth = _video_size.x;
|
||||
_dWidth = _size.x;
|
||||
_sHeight = _video_size.y;
|
||||
_dHeight = _size.y;
|
||||
|
||||
_canvas = canvas ? canvas : document.createElement("canvas");
|
||||
_canvas.width = _size.x;
|
||||
_canvas.height = _size.y;
|
||||
_canvas.width = _canvasSize.x;
|
||||
_canvas.height = _canvasSize.y;
|
||||
_ctx = _canvas.getContext("2d");
|
||||
_data = new Uint8Array(_size.x * _size.y);
|
||||
console.log("FrameGrabber", JSON.stringify({
|
||||
size: _size,
|
||||
topRight: topRight,
|
||||
videoSize: _video_size,
|
||||
canvasSize: _canvasSize
|
||||
}));
|
||||
|
||||
/**
|
||||
* Uses the given array as frame-buffer
|
||||
@@ -57,12 +54,12 @@ define(["cv_utils"], function(CVUtils) {
|
||||
frame = inputStream.getFrame(),
|
||||
ctxData;
|
||||
if (frame) {
|
||||
_ctx.drawImage(frame, _sx, _sy, _sWidth, _sHeight, _dx, _dy, _dWidth, _dHeight);
|
||||
ctxData = _ctx.getImageData(0, 0, _size.x, _size.y).data;
|
||||
_ctx.drawImage(frame, 0, 0, _canvasSize.x, _canvasSize.y);
|
||||
ctxData = _ctx.getImageData(_sx, _sy, _size.x, _size.y).data;
|
||||
if(doHalfSample){
|
||||
CVUtils.grayAndHalfSampleFromCanvasData(ctxData, _size, _data);
|
||||
} else {
|
||||
CVUtils.computeGray(ctxData, _data);
|
||||
CVUtils.computeGray(ctxData, _data, _streamConfig);
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
|
||||
@@ -23,6 +23,26 @@ define(function() {
|
||||
}
|
||||
ctx.closePath();
|
||||
ctx.stroke();
|
||||
},
|
||||
drawImage: function(imageData, size, ctx) {
|
||||
var canvasData = ctx.getImageData(0, 0, size.x, size.y),
|
||||
data = canvasData.data,
|
||||
imageDataPos = imageData.length,
|
||||
canvasDataPos = data.length,
|
||||
value;
|
||||
|
||||
if (canvasDataPos/imageDataPos !== 4) {
|
||||
return false;
|
||||
}
|
||||
while(imageDataPos--){
|
||||
value = imageData[imageDataPos];
|
||||
data[--canvasDataPos] = 255;
|
||||
data[--canvasDataPos] = value;
|
||||
data[--canvasDataPos] = value;
|
||||
data[--canvasDataPos] = value;
|
||||
}
|
||||
ctx.putImageData(canvasData, 0, 0);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+47
-2
@@ -11,7 +11,9 @@ define(["image_loader"], function(ImageLoader) {
|
||||
_eventNames = ['canrecord', 'ended'],
|
||||
_eventHandlers = {},
|
||||
_calculatedWidth,
|
||||
_calculatedHeight;
|
||||
_calculatedHeight,
|
||||
_topRight = {x: 0, y: 0},
|
||||
_canvasSize = {x: 0, y: 0};
|
||||
|
||||
function initSize() {
|
||||
var width = video.videoWidth,
|
||||
@@ -19,6 +21,9 @@ define(["image_loader"], function(ImageLoader) {
|
||||
|
||||
_calculatedWidth = _config.size ? width/height > 1 ? _config.size : Math.floor((width/height) * _config.size) : width;
|
||||
_calculatedHeight = _config.size ? width/height > 1 ? Math.floor((height/width) * _config.size) : _config.size : height;
|
||||
|
||||
_canvasSize.x = _calculatedWidth;
|
||||
_canvasSize.y = _calculatedHeight;
|
||||
}
|
||||
|
||||
that.getRealWidth = function() {
|
||||
@@ -111,6 +116,24 @@ define(["image_loader"], function(ImageLoader) {
|
||||
}
|
||||
};
|
||||
|
||||
that.setTopRight = function(topRight) {
|
||||
_topRight.x = topRight.x;
|
||||
_topRight.y = topRight.y;
|
||||
};
|
||||
|
||||
that.getTopRight = function() {
|
||||
return _topRight;
|
||||
};
|
||||
|
||||
that.setCanvasSize = function(size) {
|
||||
_canvasSize.x = size.x;
|
||||
_canvasSize.y = size.y;
|
||||
};
|
||||
|
||||
that.getCanvasSize = function() {
|
||||
return _canvasSize;
|
||||
};
|
||||
|
||||
that.getFrame = function() {
|
||||
return video;
|
||||
};
|
||||
@@ -146,7 +169,9 @@ define(["image_loader"], function(ImageLoader) {
|
||||
calculatedWidth,
|
||||
calculatedHeight,
|
||||
_eventNames = ['canrecord', 'ended'],
|
||||
_eventHandlers = {};
|
||||
_eventHandlers = {},
|
||||
_topRight = {x: 0, y: 0},
|
||||
_canvasSize = {x: 0, y: 0};
|
||||
|
||||
function loadImages() {
|
||||
loaded = false;
|
||||
@@ -156,6 +181,8 @@ define(["image_loader"], function(ImageLoader) {
|
||||
height = imgs[0].height;
|
||||
calculatedWidth = _config.size ? width/height > 1 ? _config.size : Math.floor((width/height) * _config.size) : width;
|
||||
calculatedHeight = _config.size ? width/height > 1 ? Math.floor((height/width) * _config.size) : _config.size : height;
|
||||
_canvasSize.x = calculatedWidth;
|
||||
_canvasSize.y = calculatedHeight;
|
||||
loaded = true;
|
||||
frameIdx = 0;
|
||||
setTimeout(function() {
|
||||
@@ -245,6 +272,24 @@ define(["image_loader"], function(ImageLoader) {
|
||||
}
|
||||
};
|
||||
|
||||
that.setTopRight = function(topRight) {
|
||||
_topRight.x = topRight.x;
|
||||
_topRight.y = topRight.y;
|
||||
};
|
||||
|
||||
that.getTopRight = function() {
|
||||
return _topRight;
|
||||
};
|
||||
|
||||
that.setCanvasSize = function(size) {
|
||||
_canvasSize.x = size.x;
|
||||
_canvasSize.y = size.y;
|
||||
};
|
||||
|
||||
that.getCanvasSize = function() {
|
||||
return _canvasSize;
|
||||
};
|
||||
|
||||
that.getFrame = function() {
|
||||
var frame;
|
||||
|
||||
|
||||
+122
-92
@@ -1,5 +1,5 @@
|
||||
/* jshint undef: true, unused: true, browser:true, devel: true, evil: true */
|
||||
/* global define, vec2 */
|
||||
/* global define, vec2 */
|
||||
|
||||
|
||||
define([
|
||||
@@ -15,7 +15,7 @@ define([
|
||||
"events",
|
||||
"camera_access",
|
||||
"image_debug",
|
||||
"cv_utils"],
|
||||
"result_collector"],
|
||||
function(Code128Reader,
|
||||
EANReader,
|
||||
InputStream,
|
||||
@@ -28,7 +28,7 @@ function(Code128Reader,
|
||||
Events,
|
||||
CameraAccess,
|
||||
ImageDebug,
|
||||
CVUtils) {
|
||||
ResultCollector) {
|
||||
"use strict";
|
||||
|
||||
var _inputStream,
|
||||
@@ -48,7 +48,8 @@ function(Code128Reader,
|
||||
_boxSize,
|
||||
_decoder,
|
||||
_workerPool = [],
|
||||
_onUIThread = true;
|
||||
_onUIThread = true,
|
||||
_resultCollector;
|
||||
|
||||
function initializeData(imageWrapper) {
|
||||
initBuffers(imageWrapper);
|
||||
@@ -56,20 +57,22 @@ function(Code128Reader,
|
||||
}
|
||||
|
||||
function initConfig() {
|
||||
var vis = [{
|
||||
node : document.querySelector("div[data-controls]"),
|
||||
prop : _config.controls
|
||||
}, {
|
||||
node : _canvasContainer.dom.overlay,
|
||||
prop : _config.visual.show
|
||||
}];
|
||||
if (typeof document !== "undefined") {
|
||||
var vis = [{
|
||||
node: document.querySelector("div[data-controls]"),
|
||||
prop: _config.controls
|
||||
}, {
|
||||
node: _canvasContainer.dom.overlay,
|
||||
prop: _config.visual.show
|
||||
}];
|
||||
|
||||
for (var i = 0; i < vis.length; i++) {
|
||||
if (vis[i].node) {
|
||||
if (vis[i].prop === true) {
|
||||
vis[i].node.style.display = "block";
|
||||
} else {
|
||||
vis[i].node.style.display = "none";
|
||||
for (var i = 0; i < vis.length; i++) {
|
||||
if (vis[i].node) {
|
||||
if (vis[i].prop === true) {
|
||||
vis[i].node.style.display = "block";
|
||||
} else {
|
||||
vis[i].node.style.display = "none";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -96,7 +99,7 @@ function(Code128Reader,
|
||||
if (!err) {
|
||||
_inputStream.trigger("canrecord");
|
||||
} else {
|
||||
console.log(err);
|
||||
return cb(err);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -107,39 +110,8 @@ function(Code128Reader,
|
||||
_inputStream.addEventListener("canrecord", canRecord.bind(undefined, cb));
|
||||
}
|
||||
|
||||
function checkImageConstraints() {
|
||||
var patchSize,
|
||||
width = _inputStream.getWidth(),
|
||||
height = _inputStream.getHeight(),
|
||||
halfSample = _config.locator.halfSample ? 0.5 : 1,
|
||||
size = {
|
||||
x: Math.floor(width * halfSample),
|
||||
y: Math.floor(height * halfSample)
|
||||
};
|
||||
|
||||
if (_config.locate) {
|
||||
try {
|
||||
console.log(size);
|
||||
patchSize = CVUtils.calculatePatchSize(_config.locator.patchSize, size);
|
||||
} catch (error) {
|
||||
if (error instanceof CVUtils.AdjustToSizeError) {
|
||||
_inputStream.setWidth(Math.floor(Math.floor(size.x/error.patchSize.x)*(1/halfSample)*error.patchSize.x));
|
||||
_inputStream.setHeight(Math.floor(Math.floor(size.y/error.patchSize.y)*(1/halfSample)*error.patchSize.y));
|
||||
patchSize = error.patchSize;
|
||||
}
|
||||
}
|
||||
console.log("Patch-Size: " + JSON.stringify(patchSize));
|
||||
if ((_inputStream.getWidth() % patchSize.x) === 0 && (_inputStream.getHeight() % patchSize.y) === 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
throw new Error("Image dimensions do not comply with the current settings: Width (" +
|
||||
width + " )and height (" + height +
|
||||
") must a multiple of " + patchSize.x);
|
||||
}
|
||||
|
||||
function canRecord(cb) {
|
||||
checkImageConstraints();
|
||||
BarcodeLocator.checkImageConstraints(_inputStream, _config.locator);
|
||||
initCanvas();
|
||||
_framegrabber = FrameGrabber.create(_inputStream, _canvasContainer.dom.image);
|
||||
initConfig();
|
||||
@@ -161,35 +133,37 @@ function(Code128Reader,
|
||||
}
|
||||
|
||||
function initCanvas() {
|
||||
var $viewport = document.querySelector("#interactive.viewport");
|
||||
_canvasContainer.dom.image = document.querySelector("canvas.imgBuffer");
|
||||
if (!_canvasContainer.dom.image) {
|
||||
_canvasContainer.dom.image = document.createElement("canvas");
|
||||
_canvasContainer.dom.image.className = "imgBuffer";
|
||||
if($viewport && _config.inputStream.type == "ImageStream") {
|
||||
$viewport.appendChild(_canvasContainer.dom.image);
|
||||
if (typeof document !== "undefined") {
|
||||
var $viewport = document.querySelector("#interactive.viewport");
|
||||
_canvasContainer.dom.image = document.querySelector("canvas.imgBuffer");
|
||||
if (!_canvasContainer.dom.image) {
|
||||
_canvasContainer.dom.image = document.createElement("canvas");
|
||||
_canvasContainer.dom.image.className = "imgBuffer";
|
||||
if ($viewport && _config.inputStream.type == "ImageStream") {
|
||||
$viewport.appendChild(_canvasContainer.dom.image);
|
||||
}
|
||||
}
|
||||
}
|
||||
_canvasContainer.ctx.image = _canvasContainer.dom.image.getContext("2d");
|
||||
_canvasContainer.dom.image.width = _inputStream.getWidth();
|
||||
_canvasContainer.dom.image.height = _inputStream.getHeight();
|
||||
_canvasContainer.ctx.image = _canvasContainer.dom.image.getContext("2d");
|
||||
_canvasContainer.dom.image.width = _inputStream.getCanvasSize().x;
|
||||
_canvasContainer.dom.image.height = _inputStream.getCanvasSize().y;
|
||||
|
||||
_canvasContainer.dom.overlay = document.querySelector("canvas.drawingBuffer");
|
||||
if (!_canvasContainer.dom.overlay) {
|
||||
_canvasContainer.dom.overlay = document.createElement("canvas");
|
||||
_canvasContainer.dom.overlay.className = "drawingBuffer";
|
||||
if($viewport) {
|
||||
$viewport.appendChild(_canvasContainer.dom.overlay);
|
||||
}
|
||||
var clearFix = document.createElement("br");
|
||||
clearFix.setAttribute("clear", "all");
|
||||
if($viewport) {
|
||||
$viewport.appendChild(clearFix);
|
||||
_canvasContainer.dom.overlay = document.querySelector("canvas.drawingBuffer");
|
||||
if (!_canvasContainer.dom.overlay) {
|
||||
_canvasContainer.dom.overlay = document.createElement("canvas");
|
||||
_canvasContainer.dom.overlay.className = "drawingBuffer";
|
||||
if ($viewport) {
|
||||
$viewport.appendChild(_canvasContainer.dom.overlay);
|
||||
}
|
||||
var clearFix = document.createElement("br");
|
||||
clearFix.setAttribute("clear", "all");
|
||||
if ($viewport) {
|
||||
$viewport.appendChild(clearFix);
|
||||
}
|
||||
}
|
||||
_canvasContainer.ctx.overlay = _canvasContainer.dom.overlay.getContext("2d");
|
||||
_canvasContainer.dom.overlay.width = _inputStream.getCanvasSize().x;
|
||||
_canvasContainer.dom.overlay.height = _inputStream.getCanvasSize().y;
|
||||
}
|
||||
_canvasContainer.ctx.overlay = _canvasContainer.dom.overlay.getContext("2d");
|
||||
_canvasContainer.dom.overlay.width = _inputStream.getWidth();
|
||||
_canvasContainer.dom.overlay.height = _inputStream.getHeight();
|
||||
}
|
||||
|
||||
function initBuffers(imageWrapper) {
|
||||
@@ -204,10 +178,10 @@ function(Code128Reader,
|
||||
|
||||
console.log(_inputImageWrapper.size);
|
||||
_boxSize = [
|
||||
vec2.create([20, _inputImageWrapper.size.y / 2 - 100]),
|
||||
vec2.create([20, _inputImageWrapper.size.y / 2 + 100]),
|
||||
vec2.create([_inputImageWrapper.size.x - 20, _inputImageWrapper.size.y / 2 + 100]),
|
||||
vec2.create([_inputImageWrapper.size.x - 20, _inputImageWrapper.size.y / 2 - 100])
|
||||
vec2.create([0, 0]),
|
||||
vec2.create([0, _inputImageWrapper.size.y]),
|
||||
vec2.create([_inputImageWrapper.size.x, _inputImageWrapper.size.y]),
|
||||
vec2.create([_inputImageWrapper.size.x, 0])
|
||||
];
|
||||
BarcodeLocator.init(_inputImageWrapper, _config.locator);
|
||||
}
|
||||
@@ -216,7 +190,64 @@ function(Code128Reader,
|
||||
if (_config.locate) {
|
||||
return BarcodeLocator.locate();
|
||||
} else {
|
||||
return [_boxSize];
|
||||
return [[
|
||||
vec2.create(_boxSize[0]),
|
||||
vec2.create(_boxSize[1]),
|
||||
vec2.create(_boxSize[2]),
|
||||
vec2.create(_boxSize[3])]];
|
||||
}
|
||||
}
|
||||
|
||||
function transformResult(result) {
|
||||
var topRight = _inputStream.getTopRight(),
|
||||
xOffset = topRight.x,
|
||||
yOffset = topRight.y,
|
||||
i;
|
||||
|
||||
if (!result || (xOffset === 0 && yOffset === 0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (result.line && result.line.length === 2) {
|
||||
moveLine(result.line);
|
||||
}
|
||||
if (result.boxes && result.boxes.length > 0) {
|
||||
for (i = 0; i < result.boxes.length; i++) {
|
||||
moveBox(result.boxes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
function moveBox(box) {
|
||||
var corner = box.length;
|
||||
|
||||
while(corner--) {
|
||||
box[corner][0] += xOffset;
|
||||
box[corner][1] += yOffset;
|
||||
}
|
||||
}
|
||||
|
||||
function moveLine(line) {
|
||||
line[0].x += xOffset;
|
||||
line[0].y += yOffset;
|
||||
line[1].x += xOffset;
|
||||
line[1].y += yOffset;
|
||||
}
|
||||
}
|
||||
|
||||
function publishResult(result, imageData) {
|
||||
if (_onUIThread) {
|
||||
transformResult(result);
|
||||
if (imageData && result && result.codeResult) {
|
||||
if (_resultCollector) {
|
||||
_resultCollector.addResult(imageData, _inputStream.getCanvasSize(), result.codeResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Events.publish("processed", result);
|
||||
if (result && result.codeResult) {
|
||||
Events.publish("detected", result);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -229,14 +260,10 @@ function(Code128Reader,
|
||||
result = _decoder.decodeFromBoundingBoxes(boxes);
|
||||
result = result || {};
|
||||
result.boxes = boxes;
|
||||
Events.publish("processed", result);
|
||||
if (result && result.codeResult) {
|
||||
Events.publish("detected", result);
|
||||
}
|
||||
publishResult(result, _inputImageWrapper.data);
|
||||
} else {
|
||||
Events.publish("processed");
|
||||
publishResult();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function update() {
|
||||
@@ -302,7 +329,7 @@ function(Code128Reader,
|
||||
function initWorker(cb) {
|
||||
var blobURL,
|
||||
workerThread = {
|
||||
worker: null,
|
||||
worker: undefined,
|
||||
imageData: new Uint8Array(_inputStream.getWidth() * _inputStream.getHeight()),
|
||||
busy: true
|
||||
};
|
||||
@@ -320,10 +347,7 @@ function(Code128Reader,
|
||||
} 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);
|
||||
}
|
||||
publishResult(e.data.result, workerThread.imageData);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -438,6 +462,11 @@ function(Code128Reader,
|
||||
setReaders: function(readers) {
|
||||
setReaders(readers);
|
||||
},
|
||||
registerResultCollector: function(resultCollector) {
|
||||
if (resultCollector && typeof resultCollector.addResult === 'function') {
|
||||
_resultCollector = resultCollector;
|
||||
}
|
||||
},
|
||||
canvas : _canvasContainer,
|
||||
decodeSingle : function(config, resultCallback) {
|
||||
config = HtmlUtils.mergeObjects({
|
||||
@@ -465,6 +494,7 @@ function(Code128Reader,
|
||||
Code128Reader : Code128Reader
|
||||
},
|
||||
ImageWrapper: ImageWrapper,
|
||||
ImageDebug: ImageDebug
|
||||
ImageDebug: ImageDebug,
|
||||
ResultCollector: ResultCollector
|
||||
};
|
||||
});
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
/* jshint undef: true, unused: true, browser:true, devel: true */
|
||||
/* global define */
|
||||
|
||||
define(["image_debug"], function(ImageDebug) {
|
||||
"use strict";
|
||||
|
||||
function contains(codeResult, list) {
|
||||
if (list) {
|
||||
return list.some(function (item) {
|
||||
return Object.keys(item).every(function (key) {
|
||||
return item[key] === codeResult[key];
|
||||
});
|
||||
});
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function passesFilter(codeResult, filter) {
|
||||
if (typeof filter === 'function') {
|
||||
return filter(codeResult);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return {
|
||||
create: function(config) {
|
||||
var canvas = document.createElement("canvas"),
|
||||
ctx = canvas.getContext("2d"),
|
||||
results = [],
|
||||
capacity = config.capacity || 20,
|
||||
capture = config.capture === true;
|
||||
|
||||
function matchesConstraints(codeResult) {
|
||||
return capacity && codeResult && !contains(codeResult, config.blacklist) && passesFilter(codeResult, config.filter);
|
||||
}
|
||||
|
||||
return {
|
||||
addResult: function(data, imageSize, codeResult) {
|
||||
var result = {};
|
||||
|
||||
if (matchesConstraints(codeResult)) {
|
||||
capacity--;
|
||||
result.codeResult = codeResult;
|
||||
if (capture) {
|
||||
canvas.width = imageSize.x;
|
||||
canvas.height = imageSize.y;
|
||||
ImageDebug.drawImage(data, imageSize, ctx);
|
||||
result.frame = canvas.toDataURL();
|
||||
}
|
||||
results.push(result);
|
||||
}
|
||||
},
|
||||
getResults: function() {
|
||||
return results;
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
});
|
||||
+7
-5
@@ -16,7 +16,8 @@ define(
|
||||
CODE_FREQUENCY : {value: [
|
||||
[ 56, 52, 50, 49, 44, 38, 35, 42, 41, 37 ],
|
||||
[7, 11, 13, 14, 19, 25, 28, 21, 22, 26]]},
|
||||
STOP_PATTERN: { value: [1 / 6 * 7, 1 / 6 * 7, 1 / 6 * 7, 1 / 6 * 7, 1 / 6 * 7, 1 / 6 * 7]}
|
||||
STOP_PATTERN: { value: [1 / 6 * 7, 1 / 6 * 7, 1 / 6 * 7, 1 / 6 * 7, 1 / 6 * 7, 1 / 6 * 7]},
|
||||
FORMAT: {value: "upc_e", writeable: false}
|
||||
};
|
||||
|
||||
UPCEReader.prototype = Object.create(EANReader.prototype, properties);
|
||||
@@ -35,13 +36,13 @@ define(
|
||||
if (code.code >= self.CODE_G_START) {
|
||||
code.code = code.code - self.CODE_G_START;
|
||||
codeFrequency |= 1 << (5 - i);
|
||||
} else {
|
||||
codeFrequency |= 0 << (5 - i);
|
||||
}
|
||||
result.push(code.code);
|
||||
decodedCodes.push(code);
|
||||
}
|
||||
self._determineParity(codeFrequency, result);
|
||||
if (!self._determineParity(codeFrequency, result)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return code;
|
||||
};
|
||||
@@ -56,10 +57,11 @@ define(
|
||||
if (codeFrequency === self.CODE_FREQUENCY[nrSystem][i]) {
|
||||
result.unshift(nrSystem);
|
||||
result.push(i);
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
UPCEReader.prototype._convertToUPCA = function(result) {
|
||||
|
||||
+5
-1
@@ -12,7 +12,11 @@ define(
|
||||
EANReader.call(this);
|
||||
}
|
||||
|
||||
UPCReader.prototype = Object.create(EANReader.prototype);
|
||||
var properties = {
|
||||
FORMAT: {value: "upc_a", writeable: false}
|
||||
};
|
||||
|
||||
UPCReader.prototype = Object.create(EANReader.prototype, properties);
|
||||
UPCReader.prototype.constructor = UPCReader;
|
||||
|
||||
UPCReader.prototype._decode = function() {
|
||||
|
||||
+2
-1
@@ -46,7 +46,8 @@ require.config({
|
||||
'tracer': 'src/tracer',
|
||||
'upc_e_reader': 'src/upc_e_reader',
|
||||
'upc_reader': 'src/upc_reader',
|
||||
'async': 'node_modules/async/lib/async'
|
||||
'async': 'node_modules/async/lib/async',
|
||||
'result_collector': 'src/result_collector'
|
||||
},
|
||||
deps: allTestFiles,
|
||||
callback: window.__karma__.start
|
||||
|
||||
Reference in New Issue
Block a user