Canvas getImageData报错:类型非long的问题排查与解决
Got it, let's break down what's going wrong here and how to fix it quickly.
The Failed to execute 'getImageData' on 'CanvasRenderingContext2D': Value is not of type 'long' error happens because you're passing the wrong arguments to ZXing.BitmapLuminanceSource, which leads to invalid values being used in the internal getImageData call.
Look at your line of code:
var source = new ZXing.BitmapLuminanceSource(canvas_context, video);
And check the BitmapLuminanceSource constructor logic: when the first parameter is a CanvasRenderingContext2D (your canvas_context), it expects the second parameter to be either the corresponding Canvas element or a width value. But you passed the video element instead.
The constructor treats that video as a canvas, trying to read its naturalWidth and naturalHeight. The problem is, when the camera stream just starts, those video properties might not be initialized yet (they could be 0 or NaN), which aren't valid integer values (long type) that getImageData requires. That's exactly what triggers the error.
You have a few solid options to fix this—pick whichever fits your code flow best:
Option 1: Pass the Canvas element as the second parameter
Since the constructor expects a Canvas here, just pass your existing canvas element:
// Make sure you've grabbed the canvas element first const canvas = document.getElementById('canvas'); const canvas_context = canvas.getContext('2d'); // Correctly initialize the BitmapLuminanceSource var source = new ZXing.BitmapLuminanceSource(canvas_context, canvas);
This will pull the fixed 640x480 dimensions you set on the canvas, ensuring valid integers are passed to getImageData.
Option 2: Directly pass the fixed width and height values
Since both your video and canvas are set to 640x480, you can skip relying on element properties and just pass the hardcoded dimensions:
var source = new ZXing.BitmapLuminanceSource(canvas_context, 640, 480);
Option 3: Manually get ImageData first
Another straightforward approach is to fetch the ImageData from the canvas context yourself, then pass that to the luminance source:
var imageData = canvas_context.getImageData(0, 0, 640, 480); var source = new ZXing.BitmapLuminanceSource(imageData);
- To avoid timing issues, start your barcode decoding logic only after the video has loaded its metadata (use the
video.onloadedmetadataevent). This ensures the video has valid frame dimensions before you try to capture frames. - Wrap your decoding code in a loop using
requestAnimationFrameso it continuously checks the camera feed for barcodes, instead of running just once.
内容的提问来源于stack exchange,提问作者user979331

