0

I'm creating a blazor server App that should read the Webcam and show the Image, and while the Image generates fine (the base64 is completely valid) it's not updating the image on the Website even when using InvokeAsync(StateHasChanged);

Index.razor:

@page "/"

<PageTitle>Index</PageTitle>


<div style="width: 100%; height: 500px;border: solid green 1px">
    <img src="@ImageSource" style="height: 100%; width: 100%; margin: auto; border: solid red 1px;" 
         />
</div>


@code
{

    public string? ImageSource { get; set; }

    protected override async Task OnInitializedAsync()
    {
        await base.OnInitializedAsync();

        Console.WriteLine("init");

        Webcam.Instance?.Init(async bufferScope =>
        {
            byte[] image = bufferScope.Buffer.ExtractImage();
            var ms = new MemoryStream(image);
            ImageSource = ToBase64Image(Bitmap.FromStream(ms));
            _forceRerender = true;
            await InvokeAsync(StateHasChanged);
            Console.WriteLine("running again");
        }, true);
    }

    public static string ToBase64Image(Image bmp)
    {
        var data = GetPng(bmp);

        return "data:image/png;base64," + Convert.ToBase64String(data.ToArray());
    }

    public static byte[] GetPng(Image bitmap)
    {
        using (var stream = new MemoryStream())
        {
            bitmap.Save(stream, System.Drawing.Imaging.ImageFormat.Png);
            return stream.ToArray();
        }
    }

    bool _forceRerender = false;

    protected override bool ShouldRender()
    {
        if (_forceRerender)
        {
            _forceRerender = false;
            return true;
        }
        return base.ShouldRender();
    }

}

If that helps here is my (rudimentary) webcam class (yes i know the way i have it isn't best practise but i wan't it to at least run):

using FlashCap;

namespace CameraServer.Data
{
    public class Webcam
    {
        public static Webcam? Instance { get; private set; }

        private CaptureDeviceDescriptor DeviceDescriptor { get; set; }

        public CaptureDevice Device { get; private set; }

        public Webcam(CaptureDeviceDescriptor deviceDescriptor)
        {
            DeviceDescriptor = deviceDescriptor;

            Instance = this;
        }

        public async Task<Webcam?> Init(PixelBufferArrivedDelegate func, bool start = false)
        {
            Device = await DeviceDescriptor.OpenAsync(DeviceDescriptor.Characteristics[0], func);

            if (start)
                await Device.StartAsync();

            return Instance;
        }

        //signal webcam to start
        public void Start() => Device?.StartAsync();


        //stop webcam (videoSource.WaitForStop(); to check)
        public void Stop() => Device?.StopAsync();
    }
}
9
  • Change your anonymous method attached to Webcam.Instance?.Init into a named method and using breakpoints make sure it's getting called when the webcam updates and what image you are getting. Commented Feb 16, 2023 at 17:34
  • I see no evidence that the Webcam constructor is ever called. Commented Feb 16, 2023 at 18:31
  • The Constructor is called at startup in the Program.cs, the Image also generates completely fine. I used the debugger to check the Value in ImageSource, it's a fully working image that when transplanted works as expected. I'll try using a named method Commented Feb 16, 2023 at 18:46
  • Now it's cleaner but didn't help :( Commented Feb 16, 2023 at 18:50
  • Any idea how often that PixelBufferArrivedDelegate delegate is called? Is your App still responsive? Commented Feb 16, 2023 at 19:40

1 Answer 1

0

If someone has a similar problem: The Issue was solved by changing the render-mode in _Host.cshtml from "ServerPrerendered" to "Server".

Thanks everyone who tried to help!

Sign up to request clarification or add additional context in comments.

3 Comments

That alone cannot explain the error. The main difference is that with ServerPrerendered Index.OnInitializedAsync() is called twice. You will now probably see the same issue when you change pages.
Yes that's the case, but i already expected that. This can (and has been) fixed by moving the methods that generate the Image to the Webcam class and Getting the source from there. However without changing the rendering this wouldn't work at all.
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.