Comparing version 0.6.9 to 0.6.10
@@ -37,3 +37,3 @@ module.exports = function(grunt) { | ||
"name" : "quagga", | ||
"useStrict": false, | ||
"useStrict": true, | ||
"out" : "dist/quagga.js", | ||
@@ -40,0 +40,0 @@ "include" : ['quagga'], |
{ | ||
"name": "quagga", | ||
"version": "0.6.9", | ||
"version": "0.6.10", | ||
"description": "An advanced barcode-scanner written in JavaScript", | ||
@@ -5,0 +5,0 @@ "main": "dist/quagga.js", |
quaggaJS | ||
======== | ||
- [Changelog](#changelog) (2015-06-14) | ||
- [Changelog](#changelog) (2015-06-21) | ||
@@ -227,3 +227,4 @@ ## What is QuaggaJS? | ||
bottom: "0%" // bottom offset | ||
} | ||
}, | ||
singleChannel: false // true: only the red color-channel is read | ||
}, | ||
@@ -302,4 +303,67 @@ tracking: false, | ||
## <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-06-21 | ||
- Features | ||
- Added ``singleChannel`` configuration to ``inputStream`` (in [config] | ||
(#configobject)) | ||
- Added ``ResultCollector`` functionality (see [ResultCollector] | ||
(#resultcollector)) | ||
### 2015-06-13 | ||
@@ -306,0 +370,0 @@ - Improvements |
@@ -74,5 +74,5 @@ | ||
{"name": "image-001.jpg", "result": "0001285112001000040801"}, | ||
// {"name": "image-002.jpg", "result": "FANAVF1461710"}, | ||
{"name": "image-002.jpg", "result": "FANAVF1461710"}, | ||
// {"name": "image-003.jpg", "result": "673023"}, | ||
{"name": "image-004.jpg", "result": "010210150301625334"}, | ||
// {"name": "image-004.jpg", "result": "010210150301625334"}, | ||
{"name": "image-005.jpg", "result": "419055603900009001012999"}, | ||
@@ -79,0 +79,0 @@ {"name": "image-006.jpg", "result": "419055603900009001012999"}, |
@@ -21,3 +21,4 @@ /** | ||
bottom: "0%" | ||
} | ||
}, | ||
singleChannel: false // true: only the red color-channel is read | ||
}, | ||
@@ -24,0 +25,0 @@ tracking: false, |
@@ -487,9 +487,15 @@ /* jshint undef: true, unused: true, browser:true, devel: true */ | ||
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]); | ||
} | ||
} | ||
@@ -496,0 +502,0 @@ }; |
@@ -62,3 +62,3 @@ /* jshint undef: true, unused: true, browser:true, devel: true */ | ||
} else { | ||
CVUtils.computeGray(ctxData, _data); | ||
CVUtils.computeGray(ctxData, _data, _streamConfig); | ||
} | ||
@@ -65,0 +65,0 @@ return true; |
@@ -26,2 +26,22 @@ /* jshint undef: true, unused: true, browser:true, devel: true */ | ||
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; | ||
} | ||
@@ -28,0 +48,0 @@ }; |
/* jshint undef: true, unused: true, browser:true, devel: true, evil: true */ | ||
/* global define, vec2 */ | ||
/* global define, vec2 */ | ||
@@ -17,3 +17,4 @@ | ||
"camera_access", | ||
"image_debug"], | ||
"image_debug", | ||
"result_collector"], | ||
function(Code128Reader, | ||
@@ -30,3 +31,4 @@ EANReader, | ||
CameraAccess, | ||
ImageDebug) { | ||
ImageDebug, | ||
ResultCollector) { | ||
"use strict"; | ||
@@ -51,3 +53,4 @@ | ||
_workerPool = [], | ||
_onUIThread = true; | ||
_onUIThread = true, | ||
_resultCollector; | ||
@@ -60,16 +63,18 @@ function initializeData(imageWrapper) { | ||
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"; | ||
} | ||
} | ||
@@ -137,31 +142,33 @@ } | ||
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.getCanvasSize().x; | ||
_canvasContainer.dom.image.height = _inputStream.getCanvasSize().y; | ||
_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); | ||
_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); | ||
} | ||
} | ||
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.getCanvasSize().x; | ||
_canvasContainer.dom.overlay.height = _inputStream.getCanvasSize().y; | ||
} | ||
@@ -234,6 +241,12 @@ | ||
function publishResult(result) { | ||
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); | ||
@@ -254,3 +267,3 @@ if (result && result.codeResult) { | ||
result.boxes = boxes; | ||
publishResult(result); | ||
publishResult(result, _inputImageWrapper.data); | ||
} else { | ||
@@ -324,3 +337,3 @@ publishResult(); | ||
workerThread = { | ||
worker: null, | ||
worker: undefined, | ||
imageData: new Uint8Array(_inputStream.getWidth() * _inputStream.getHeight()), | ||
@@ -343,3 +356,3 @@ busy: true | ||
workerThread.busy = false; | ||
publishResult(e.data.result); | ||
publishResult(e.data.result, workerThread.imageData); | ||
} | ||
@@ -459,2 +472,7 @@ }; | ||
}, | ||
registerResultCollector: function(resultCollector) { | ||
if (resultCollector && typeof resultCollector.addResult === 'function') { | ||
_resultCollector = resultCollector; | ||
} | ||
}, | ||
canvas : _canvasContainer, | ||
@@ -487,4 +505,5 @@ decodeSingle : function(config, resultCallback) { | ||
ImageWrapper: ImageWrapper, | ||
ImageDebug: ImageDebug | ||
ImageDebug: ImageDebug, | ||
ResultCollector: ResultCollector | ||
}; | ||
}); |
@@ -49,3 +49,4 @@ var allTestFiles = []; | ||
'upc_reader': 'src/upc_reader', | ||
'async': 'node_modules/async/lib/async' | ||
'async': 'node_modules/async/lib/async', | ||
'result_collector': 'src/result_collector' | ||
}, | ||
@@ -52,0 +53,0 @@ deps: allTestFiles, |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
1941425
58
43756
460