Giter Site home page Giter Site logo

Comments (9)

ManuelKetisch avatar ManuelKetisch commented on May 24, 2024 1

Update:
I figured out how i can trigger my methods using MVVM Community Toolkit.
I had to declare partial methods for the auto generated observables, like this:

[ObservableProperty] private CaptureDeviceDescriptor? _deviceDescriptor;
[ObservableProperty] private VideoCharacteristics? _characteristic;

partial void OnDeviceDescriptorChanged(CaptureDeviceDescriptor? descriptor)
{
    OnDeviceListChangedAsync(descriptor);
}

partial void OnCharacteristicChanged(VideoCharacteristics? characteristic)
{
     OnCharacteristicsChangedAsync(characteristic);
}

Now the sample code is working and i get images streamed to my SKImageView.

Now i have another question.
The Window which hosts the SKImageView has a button, which when pressed, should take a snapshot from the current stream and store it in the parent windows image control.

What would be the best approach to take a single shot from the current image stream?
Should i use the already available stored Bitmap from the Image property or should i handle this seperately, for example by using the TakeOneShotAsync method?

Edit: The image does not need to be stored as a file on the system when captured. This will be handled seperately in a save data method.

from flashcap.

kekyo avatar kekyo commented on May 24, 2024

Thanks reached out!

This sample code uses an MVVM framework called Epoxy that I maintain. Methods with PropertyChanged attributes as follows: OnDeviceListChangedAsync()

    [PropertyChanged(nameof(Device))]
    private ValueTask OnDeviceListChangedAsync(CaptureDeviceDescriptor? descriptor)
    { ... }

is called by Epoxy when a property of that name is changed. The argument is passed a modified value, which can be used to perform additional operations.

The Device property is updated with data binding when the device is changed from the combo box, so this method is called at that time to update the list of characteristics.

The method signature must return a ValueTask as in this example; Epoxy generates code at build time for all property changes, including code to properly supplement unhandled exceptions.

Is there anything else you don't understand?

from flashcap.

ManuelKetisch avatar ManuelKetisch commented on May 24, 2024

Ok thanks for clarifying this for me.
I thought it had something to do with the Epoxy MVVM Framework.

Since i am using Microsofts MVVM Community Toolkit for my application, this Framework handles things a little bit diffrently. For Example: I can only assing the NotifyProperyChangedFor attribute to fields, not methods.
Therefore i need to figure out a different way to trigger these methods when the device or characteristic is changing.

Assigning the RelayCommand attribute to the methods and NotifyCanExecuteChangedFor to the Device property doesn't do the trick.

I will see if i can get some help to make this work with MVVM Community Toolkit, since this issue has nothing to do with your FlashCap library.

from flashcap.

kekyo avatar kekyo commented on May 24, 2024

Should i use the already available stored Bitmap from the Image property

This is a good idea. There is no special function in FlashCap that holds continuous image data.

One thing to consider is the possibility that a handler OnPixelBufferArrivedAsync() is called in a different thread than the UI thread, so there may be a race condition in saving and retrieving the SKBitmap.

However, since SKBitmap is a reference object (objref), holding it in a field or property would not be a problem if it were referenced by another handler (e.g., a button click handler).

Perhaps you are storing the decoded SKbitmap in a property to bind it to the SkiaImageView. You could save it using that value like:

// Save SKBitmap into png.
using (var fs = new FileStream(...))
{
    this.Image.Encode(fs, SKEncodedImageFormat.Png, 100);
    await fs.FlushAsync();
}

Or, if you really want to output the raw data captured by FlashCap to a file as it is, you can keep it as byte[] in a private field and refer to it. In this case, do not forget to use PixelBuffer.CopyImage() instead of PixelBuffer.ExtractImage() and PixelBuffer.ReferImage() to retrieve it.

private byte[]? imageData;

// Get image data binary and save
this.imageData = bufferScope.Buffer.CopyImage();

from flashcap.

ManuelKetisch avatar ManuelKetisch commented on May 24, 2024

Thanks for the advice. I am currently trying to make use of the SKBitmap directly by storing it in another ViewModels SKBitmap property. However, despite the fact, that the property is an ObservableProperty, the changing value does not trigger the View to update. Do you have any ideas why that is the case?

I have a MainView with its corresponding MainViewModel.
The MainView has an Image control and a button.
When the button is pressed, a secondary Window opens, which is the capture window.
This capture window has a button, when pressed, stores the image in a property of the capture windows ViewModel.
I then hand over the SKBitmap data from the ImageCaptureViewModel to the MainViewModel.

MainViewModel:

        [ObservableProperty] private SKBitmap? _currentImage11;

        [RelayCommand]
        private async Task CaptureImageButtonPressed(MainWindow ownerWindow)
        {
            await new ImageCaptureWindow().ShowDialog(ownerWindow);
        }

ImageCaptureWindowViewModel:

        [ObservableProperty] private SKBitmap? _image;

        [RelayCommand]
        private async Task CaptureImageButtonPressed(ImageCaptureWindow captureWindow)
        {
            _currentWindow = captureWindow;
            MainView mainView = new();

            var captureDevice = _captureDevice;
            captureDevice.StopAsync();

            _mainViewModel.CurrentImage11 = Image;
            _currentWindow.Close();
        }

Now i would expect the CurrentImage11 ObservableProperty to update the MainView Image Control:

                        <siv:SKImageView Width="600" Height="600"
                                         x:Name="SkImageView1"
                                         HorizontalAlignment="Center" VerticalAlignment="Center"
                                         Source="{Binding CurrentImage11, Mode=TwoWay}"
                                         Stretch="Uniform" />

But for some reason i does not update the view. I am missing something... but can't figure our what it is.
How would you do it?

from flashcap.

kekyo avatar kekyo commented on May 24, 2024

I have no experience with the MVVM Community Toolkit, so I can't give you solid advice, but I am curious about something.

  • Where does the ImageCaptureWindowViewModel._mainViewModel come from?
    It seems to me that if this is passed correctly from MainViewModel, it should work fine.
  • Also, the MainView mainView = new(); line doesn't seem to make sense.

from flashcap.

ManuelKetisch avatar ManuelKetisch commented on May 24, 2024

Where does the ImageCaptureWindowViewModel._mainViewModel come from?

I instantiated it in the class constructor, but for some reason it does not trigger the notify property changed when the value of the property changes.

Also, the MainView mainView = new(); line doesn't seem to make sense.

Correct, that was experimental, and is no longer present in my code.

Anyways, i figured out, that MVVM Community Toolkit features messaging (sender, recipients), which allows for communication between different elements of an application (Models, Views, ViewModels). Now the property triggers notify property changed correctly and i am getting closer to my goal.

Thanks for the assistance.

from flashcap.

kekyo avatar kekyo commented on May 24, 2024

If I am not mistaken,
When you create an instance of MainViewModel in the constructor of ImageCaptureWindowViewModel, no changes are transmitted to the "original" MainViewModel.

In this state, two instances of MainViewModel exist, and a new instance of MainViewModel is created and held separately from the instance of MainViewModel that is attached to the View on the display.

Assuming that ImageCaptureWindowViewModel._mainViewModel holds this second instance, any changes to this instance will not (automatically) be notified to the original instance.

There is no generally established way for the view model of a dialog-like view and the original view model to communicate with each other. For example, the party displaying the dialog would need to provide an explicit way to transfer:

// Construct new dialog view.
var dialog = new SubDialogWindow();

// HACK: Transfer this (main) view model reference into dialog view model.
((SubDialogViewModel)dialog.DataContext)._mainViewModel = this;

// Show.
dialog.Show();

As you can see this is dirty code, and some MVVM frameworks may have smart ways to assist with this.

(Epoxy does not, because Epoxy assumes an SPA-like style as in Web UI, and does not intend to take advantage of dialogs.)

from flashcap.

kekyo avatar kekyo commented on May 24, 2024

If there seem to be further problems, please reopen.

from flashcap.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.