Skip to content

Commit

Permalink
Fix #150: reintroduce lib/frame_grabber input_stream as src/input/*_n…
Browse files Browse the repository at this point in the history
…ode.js

- do not use webpack tricks to build them, so that it is obvious they are
  used in the source, where and why, and so that test coverage can be
  checked with them decently
  • Loading branch information
ericblade committed Mar 23, 2020
1 parent 7bc8b07 commit aad4e26
Show file tree
Hide file tree
Showing 6 changed files with 259 additions and 3 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@ericblade/quagga2",
"version": "0.0.18",
"version": "0.0.19",
"description": "An advanced barcode-scanner written in JavaScript",
"main": "lib/quagga.js",
"types": "type-definitions/quagga.d.ts",
Expand Down
3 changes: 3 additions & 0 deletions src/input/frame_grabber.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import NodeFrameGrabber from './frame_grabber_node';

import {
imageRef,
grayAndHalfSampleFromCanvasData,
Expand Down Expand Up @@ -120,3 +122,4 @@ FrameGrabber.create = function(inputStream, canvas) {
};

export default FrameGrabber;
export { NodeFrameGrabber };
95 changes: 95 additions & 0 deletions src/input/frame_grabber_node.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
const CVUtils = require('../common/cv_utils'),
Ndarray = require("ndarray"),
Interp2D = require("ndarray-linear-interpolate").d2;

var FrameGrabber = {};

FrameGrabber.create = function(inputStream) {
var _that = {},
_streamConfig = inputStream.getConfig(),
_video_size = CVUtils.imageRef(inputStream.getRealWidth(), inputStream.getRealHeight()),
_canvasSize = inputStream.getCanvasSize(),
_size = CVUtils.imageRef(inputStream.getWidth(), inputStream.getHeight()),
_topRight = inputStream.getTopRight(),
_data = new Uint8Array(_size.x * _size.y),
_grayData = new Uint8Array(_video_size.x * _video_size.y),
_canvasData = new Uint8Array(_canvasSize.x * _canvasSize.y),
_grayImageArray = Ndarray(_grayData, [_video_size.y, _video_size.x]).transpose(1, 0),
_canvasImageArray = Ndarray(_canvasData, [_canvasSize.y, _canvasSize.x]).transpose(1, 0),
_targetImageArray = _canvasImageArray.hi(_topRight.x + _size.x, _topRight.y + _size.y).lo(_topRight.x, _topRight.y),
_stepSizeX = _video_size.x/_canvasSize.x,
_stepSizeY = _video_size.y/_canvasSize.y;

console.log("FrameGrabber", JSON.stringify({
videoSize: _grayImageArray.shape,
canvasSize: _canvasImageArray.shape,
stepSize: [_stepSizeX, _stepSizeY],
size: _targetImageArray.shape,
topRight: _topRight
}));

/**
* Uses the given array as frame-buffer
*/
_that.attachData = function(data) {
_data = data;
};

/**
* Returns the used frame-buffer
*/
_that.getData = function() {
return _data;
};

/**
* Fetches a frame from the input-stream and puts into the frame-buffer.
* The image-data is converted to gray-scale and then half-sampled if configured.
*/
_that.grab = function() {
var frame = inputStream.getFrame();

if (frame) {
this.scaleAndCrop(frame);
return true;
} else {
return false;
}
};

_that.scaleAndCrop = function(frame) {
var x,
y;

// 1. compute full-sized gray image
CVUtils.computeGray(frame.data, _grayData);

// 2. interpolate
for (y = 0; y < _canvasSize.y; y++) {
for (x = 0; x < _canvasSize.x; x++) {
_canvasImageArray.set(x, y, (Interp2D(_grayImageArray, x * _stepSizeX, y * _stepSizeY)) | 0);
}
}

// targetImageArray must be equal to targetSize
if (_targetImageArray.shape[0] !== _size.x ||
_targetImageArray.shape[1] !== _size.y) {
throw new Error("Shapes do not match!");
}

// 3. crop
for (y = 0; y < _size.y; y++) {
for (x = 0; x < _size.x; x++) {
_data[y * _size.x + x] = _targetImageArray.get(x, y);
}
}
},

_that.getSize = function() {
return _size;
};

return _that;
};

module.exports = FrameGrabber;
2 changes: 2 additions & 0 deletions src/input/input_stream.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import NodeInputStream from './input_stream_node';
import ImageLoader from './image_loader';

var InputStream = {};
Expand Down Expand Up @@ -328,3 +329,4 @@ InputStream.createImageStream = function() {
};

export default InputStream;
export { NodeInputStream };
153 changes: 153 additions & 0 deletions src/input/input_stream_node.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
const GetPixels = require("get-pixels");

var InputStream = {};

InputStream.createImageStream = function() {
var that = {};
var _config = null;

var width = 0,
height = 0,
frameIdx = 0,
paused = true,
loaded = false,
frame = null,
baseUrl,
ended = false,
size,
calculatedWidth,
calculatedHeight,
_eventNames = ['canrecord', 'ended'],
_eventHandlers = {},
_topRight = {x: 0, y: 0},
_canvasSize = {x: 0, y: 0};

function loadImages() {
loaded = false;
GetPixels(baseUrl, _config.mime, function(err, pixels) {
if (err) {
console.error('**** quagga loadImages error:', err);
throw new Error('error decoding pixels in loadImages');
}
loaded = true;
console.log(pixels.shape);
frame = pixels;
width = pixels.shape[0];
height = pixels.shape[1];
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;

setTimeout(function() {
publishEvent("canrecord", []);
}, 0);
});
}

function publishEvent(eventName, args) {
var j,
handlers = _eventHandlers[eventName];

if (handlers && handlers.length > 0) {
for ( j = 0; j < handlers.length; j++) {
handlers[j].apply(that, args);
}
}
}


that.trigger = publishEvent;

that.getWidth = function() {
return calculatedWidth;
};

that.getHeight = function() {
return calculatedHeight;
};

that.setWidth = function(width) {
calculatedWidth = width;
};

that.setHeight = function(height) {
calculatedHeight = height;
};

that.getRealWidth = function() {
return width;
};

that.getRealHeight = function() {
return height;
};

that.setInputStream = function(stream) {
_config = stream;
baseUrl = _config.src;
size = 1;
loadImages();
};

that.ended = function() {
return ended;
};

that.setAttribute = function() {};

that.getConfig = function() {
return _config;
};

that.pause = function() {
paused = true;
};

that.play = function() {
paused = false;
};

that.setCurrentTime = function(time) {
frameIdx = time;
};

that.addEventListener = function(event, f) {
if (_eventNames.indexOf(event) !== -1) {
if (!_eventHandlers[event]) {
_eventHandlers[event] = [];
}
_eventHandlers[event].push(f);
}
};

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() {
if (!loaded){
return null;
}
return frame;
};

return that;
};

module.exports = InputStream;
7 changes: 5 additions & 2 deletions src/quagga.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,15 @@ import CameraAccess from './input/camera_access.ts';
import ImageDebug from './common/image_debug.ts';
import ResultCollector from './analytics/result_collector.ts';
import Config from './config/config';
import InputStream from './input/input_stream';
import FrameGrabber from './input/frame_grabber';
import BrowserInputStream, { NodeInputStream } from './input/input_stream';
import BrowserFrameGrabber, { NodeFrameGrabber } from './input/frame_grabber';
import { merge } from 'lodash';
import { clone } from 'gl-vec2';
const vec2 = { clone };

const InputStream = typeof window === 'undefined' ? NodeInputStream : BrowserInputStream;
const FrameGrabber = typeof window === 'undefined' ? NodeFrameGrabber : BrowserFrameGrabber;

// export BarcodeReader and other utilities for external plugins
export { BarcodeReader, BarcodeDecoder, ImageWrapper, ImageDebug, ResultCollector, CameraAccess };

Expand Down

0 comments on commit aad4e26

Please sign in to comment.