I have a Blazor WebAssembly application capturing video from the computer webcam. The video Element linked to the webcam is hidden. The Video feed is painted to an HTML canvas element.
I am using JSInterop to call GetImageData() on the canvas. The function returns an image of part of the canvas as an image.
When I return the image from the JavaScript function I get a:
"dotnet.wasm:1 Uncaught (in promise) RuntimeError: memory access out of bounds error"
Here is the HTML:
<div id="container">
<video id="videoElement" @ref="VideoElement" autoplay="true" width="1280" height="720"></video>
<canvas id="videoCanvas" @ref="VideoCanvas" width="1280" height="720"></canvas>
</div>
Here is the code causing the issue. I've narrowed it down to the line in OnTimedEvent:
@code {
ElementReference VideoElement;
ElementReference VideoCanvas;
protected async override Task OnAfterRenderAsync(bool firstRender)
{
await JSRuntime.InvokeVoidAsync("StartVideo", VideoElement);
await JSRuntime.InvokeVoidAsync("PaintVideoToCanvas", VideoElement, VideoCanvas);
Timer _timer = new Timer(5000);
_timer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
_timer.Start();
}
private async void OnTimedEvent(object source, ElapsedEventArgs e)
{
Image temp = await JSRuntime.InvokeAsync<Image>("ImageScanner", VideoCanvas);
}
}
Here is the JavaScript:
function StartVideo(VideoElement) {
let video = VideoElement;
if (navigator.mediaDevices.getUserMedia) {
navigator.mediaDevices.getUserMedia({ video: { width: { min: 1280 }, height: { min: 720 } } })
.then(function (stream) {
video.srcObject = stream;
})
.catch(function (err0r) {
console.log("Something went wrong!");
});
}
}
function PaintVideoToCanvas(VideoElement, VideoCanvas) {
let video = VideoElement;
let canvas = VideoCanvas;
let ctxLayer1 = canvas.getContext("2d");
StartVideo();
function StartVideo() {
ctxLayer1.drawImage(video, 0, 0);
setTimeout(StartVideo, 1000 / 30); // drawing at 30fps
}
}
function ImageScanner(VideoCanvas) {
let video = VideoCanvas;
let ctxQRCapture = video.getContext("2d");
let image = ctxQRCapture.getImageData(950, 260, 200, 200);
return image;
}