I have a video and canvas element like so:
<video id="video" width="640" height="480"></video>
<canvas id="canvas" width="640" height="480"></canvas>
and what I am trying to do is decode a PDF417 barcode from my web cam.
Here is the code that gets the permission to use the web cam:
if(navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
navigator.mediaDevices.getUserMedia({ video: true }).then(function(stream) {
video.srcObject = stream;
video.play();
});
}
And this is where I try to use the camera to capture the barcode and decode it:
canvas_context.drawImage(video, 0, 0, 640, 480);
try {
var source = new ZXing.BitmapLuminanceSource(canvas_context, video);
var binarizer = new ZXing.Common.HybridBinarizer(source);
var bitmap = new ZXing.BinaryBitmap(binarizer);
console.log(JSON.stringify(ZXing.PDF417.PDF417Reader.decode(bitmap, null, false), null, 4));
} catch (err) {
console.log(err);
}
However I am getting this error:
Failed to execute 'getImageData' on 'CanvasRenderingContext2D': Value is not of type 'long'.
On this line:
var source = new ZXing.BitmapLuminanceSource(canvas_context, video);
Which calls this method:
ZXing.BitmapLuminanceSource = function (bitmap, w, h) {
var debug = typeof window != 'undefined' && window.__debug === true;
var width, height;
if (typeof bitmap == 'number') {
width = bitmap;
height = w;
ZXing.BaseLuminanceSource.call(this, width, height);
} else {
var canvas, data;
if (bitmap instanceof Uint8ClampedArray) {
width = w;
height = h;
data = bitmap;
} else if (bitmap instanceof ImageData) {
width = w || bitmap.width;
height = h || bitmap.height;
data = bitmap.data;
} else {
canvas = w;
width = canvas.naturalWidth;
height = canvas.naturalHeight;
var imageData = bitmap.getImageData(0, 0, width, height);
data = imageData.data;
}
ZXing.BaseLuminanceSource.call(this, width, height);
var stride = Math.abs(data.length / height);
if (debug) this.debugBitmap = [];
//console.time("luminances")
for(var y = 0; y < height; y++) {
var strideOffset = y * stride;
var maxIndex = (4 * width) + strideOffset;
for(var x = strideOffset; x < maxIndex; x += 4) {
var luminance = ((7424 * data[x] + 38550 * data[x + 1] + 19562 * data[x + 2]) >> 16);
//var alpha = data[x + 3];
//luminance = (((luminance * alpha) >> 8) + (255 * (255 - alpha) >> 8) + 1);
//luminance = luminance < 50 ? 1 : (luminance > 90 ? 255 : luminance)
this.luminances.push(luminance);
if (debug) {
this.debugBitmap.push(luminance);
this.debugBitmap.push(luminance);
this.debugBitmap.push(luminance);
this.debugBitmap.push(255);
}
}
}
//console.timeEnd("luminances")
}
};
What am I doing wrong? Why am I getting this error and how do I fix it?
I have a video and canvas element like so:
<video id="video" width="640" height="480"></video>
<canvas id="canvas" width="640" height="480"></canvas>
and what I am trying to do is decode a PDF417 barcode from my web cam.
Here is the code that gets the permission to use the web cam:
if(navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
navigator.mediaDevices.getUserMedia({ video: true }).then(function(stream) {
video.srcObject = stream;
video.play();
});
}
And this is where I try to use the camera to capture the barcode and decode it:
canvas_context.drawImage(video, 0, 0, 640, 480);
try {
var source = new ZXing.BitmapLuminanceSource(canvas_context, video);
var binarizer = new ZXing.Common.HybridBinarizer(source);
var bitmap = new ZXing.BinaryBitmap(binarizer);
console.log(JSON.stringify(ZXing.PDF417.PDF417Reader.decode(bitmap, null, false), null, 4));
} catch (err) {
console.log(err);
}
However I am getting this error:
Failed to execute 'getImageData' on 'CanvasRenderingContext2D': Value is not of type 'long'.
On this line:
var source = new ZXing.BitmapLuminanceSource(canvas_context, video);
Which calls this method:
ZXing.BitmapLuminanceSource = function (bitmap, w, h) {
var debug = typeof window != 'undefined' && window.__debug === true;
var width, height;
if (typeof bitmap == 'number') {
width = bitmap;
height = w;
ZXing.BaseLuminanceSource.call(this, width, height);
} else {
var canvas, data;
if (bitmap instanceof Uint8ClampedArray) {
width = w;
height = h;
data = bitmap;
} else if (bitmap instanceof ImageData) {
width = w || bitmap.width;
height = h || bitmap.height;
data = bitmap.data;
} else {
canvas = w;
width = canvas.naturalWidth;
height = canvas.naturalHeight;
var imageData = bitmap.getImageData(0, 0, width, height);
data = imageData.data;
}
ZXing.BaseLuminanceSource.call(this, width, height);
var stride = Math.abs(data.length / height);
if (debug) this.debugBitmap = [];
//console.time("luminances")
for(var y = 0; y < height; y++) {
var strideOffset = y * stride;
var maxIndex = (4 * width) + strideOffset;
for(var x = strideOffset; x < maxIndex; x += 4) {
var luminance = ((7424 * data[x] + 38550 * data[x + 1] + 19562 * data[x + 2]) >> 16);
//var alpha = data[x + 3];
//luminance = (((luminance * alpha) >> 8) + (255 * (255 - alpha) >> 8) + 1);
//luminance = luminance < 50 ? 1 : (luminance > 90 ? 255 : luminance)
this.luminances.push(luminance);
if (debug) {
this.debugBitmap.push(luminance);
this.debugBitmap.push(luminance);
this.debugBitmap.push(luminance);
this.debugBitmap.push(255);
}
}
}
//console.timeEnd("luminances")
}
};
What am I doing wrong? Why am I getting this error and how do I fix it?
Share Improve this question edited Nov 19, 2019 at 14:45 Kaiido 138k14 gold badges260 silver badges325 bronze badges asked Nov 19, 2019 at 14:11 user979331user979331 12k83 gold badges248 silver badges451 bronze badges 02 Answers
Reset to default 3This function accepts (among many other things) an HTMLImageElement as w
parameter, from which it will get its naturalWidth
and naturalHeight
properties. An HTMLVideoElement doesn't have these properties (but videoWidth
and videoHeight
).
So given the plex signature of this function, the easiest might be to pass yourself an ImageData there:
const data = canvas_context.getImageData(0, 0, 640, 480);
source = new ZXing.BitmapLuminanceSource(data)
Your code is confusing. In your call to BitmapLuminanceSource
you use 2 parameters (a canvas context and a video [source]), while the function definition itself uses (bitmap, w, h) as arguments (which a casual reader would interpret as a bitmap, together with its width and height parameters).
Then, you suddenly define a variable with the name of canvas -- but a canvas and its context always go together i.e. if you really needed a canvas object, you would have injected it together with its context.
Next, you assign the input parameter w to this new canvas variable. This is highly confusing, as in the code above you equal w repeatedly to a width parameter.
Assuming w is actually the canvas belonging to the canvas context mentioned earlier, we then e to the gist of your problem: both width and height in your call to getImageData
are undefined (or zero): the canvas element itself does not have a naturalWidth or naturalHeight property, only an imageElement
does.
This is what causes the 'Value is not of type 'long'' error notification.